diff --git a/src/bin/hexyl.rs b/src/bin/hexyl.rs index acc6a28..db0a82d 100644 --- a/src/bin/hexyl.rs +++ b/src/bin/hexyl.rs @@ -3,14 +3,15 @@ extern crate clap; use atty; +use std::cell::RefCell; use std::fs::File; -use std::io::{self, prelude::*}; +use std::io::{self, prelude::*, SeekFrom}; use clap::{App, AppSettings, Arg}; use atty::Stream; -use hexyl::{BorderStyle, Printer}; +use hexyl::{BorderStyle, Input, Printer}; fn run() -> Result<(), Box> { let app = App::new(crate_name!()) @@ -37,6 +38,14 @@ fn run() -> Result<(), Box> { .value_name("N") .help("An alias for -n/--length"), ) + .arg( + Arg::with_name("skip") + .short("s") + .long("skip") + .takes_value(true) + .value_name("N") + .help("Skip first N bytes"), + ) .arg( Arg::with_name("nosqueezing") .short("v") @@ -80,16 +89,24 @@ fn run() -> Result<(), Box> { let stdin = io::stdin(); - let mut reader: Box = match matches.value_of("file") { - Some(filename) => Box::new(File::open(filename)?), - None => Box::new(stdin.lock()), + let mut reader: Input = match matches.value_of("file") { + Some(filename) => Input::File(File::open(filename)?), + None => Input::Stdin(RefCell::new(stdin.lock())), }; + let skip_arg = matches.value_of("skip"); + + if let Some(length) = skip_arg.and_then(parse_hex_or_int) { + reader.seek(SeekFrom::Start(length))?; + } + let length_arg = matches.value_of("length").or(matches.value_of("bytes")); - if let Some(length) = length_arg.and_then(parse_hex_or_int) { - reader = Box::new(reader.take(length)); - } + let mut reader = if let Some(length) = length_arg.and_then(parse_hex_or_int) { + Box::new(reader.take(length)) + } else { + reader.into_inner() + }; let show_color = match matches.value_of("color") { Some("never") => false, diff --git a/src/input.rs b/src/input.rs new file mode 100644 index 0000000..131541a --- /dev/null +++ b/src/input.rs @@ -0,0 +1,38 @@ +use std::cell::RefCell; +use std::fs; +use std::io::{self, Read, Seek, SeekFrom}; + +pub enum Input<'a> { + File(fs::File), + Stdin(RefCell>), +} + +impl<'a> Read for Input<'a> { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + match *self { + Input::File(ref mut file) => file.read(buf), + Input::Stdin(ref mut stdin) => stdin.borrow_mut().read(buf), + } + } +} + +impl<'a> Seek for Input<'a> { + fn seek(&mut self, pos: SeekFrom) -> io::Result { + match *self { + Input::File(ref mut file) => file.seek(pos), + Input::Stdin(_) => Err(io::Error::new( + io::ErrorKind::Other, + "not supported by stdin-input", + )), + } + } +} + +impl<'a> Input<'a> { + pub fn into_inner(self) -> Box { + match self { + Self::File(file) => Box::new(file), + Self::Stdin(stdin) => Box::new(stdin.into_inner()), + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 08fd4d8..c818107 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,8 @@ +pub(crate) mod input; pub mod squeezer; +pub use input::*; + use std::io::{self, Read, Write}; use ansi_term::Color; @@ -407,7 +410,7 @@ impl<'a, Writer: Write> Printer<'a, Writer> { /// is exhausted. pub fn print_all( &mut self, - mut reader: Reader + mut reader: Reader, ) -> Result<(), Box> { let mut buffer = [0; BUFFER_SIZE]; 'mainloop: loop {