diff --git a/Cargo.lock b/Cargo.lock index 8c1752b..dd51344 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,14 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b476ce7103678b0c6d3d395dbbae31d48ff910bd28be979ba5d48c6351131d0d" +dependencies = [ + "memchr", +] + [[package]] name = "ansi_term" version = "0.11.0" @@ -48,6 +57,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + [[package]] name = "bitflags" version = "1.2.1" @@ -81,6 +96,15 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +[[package]] +name = "float-cmp" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1267f4ac4f343772758f7b1bdcbe767c218bbab93bb432acbf5162bbf85a6c4" +dependencies = [ + "num-traits", +] + [[package]] name = "hermit-abi" version = "0.1.13" @@ -100,15 +124,43 @@ dependencies = [ "atty", "clap", "libc", + "predicates", "thiserror", ] +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49" +[[package]] +name = "memchr" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" + +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + [[package]] name = "predicates" version = "1.0.5" @@ -116,7 +168,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96bfead12e90dccead362d62bb2c90a5f6fc4584963645bc7f71a735e0b0735a" dependencies = [ "difference", + "float-cmp", + "normalize-line-endings", "predicates-core", + "regex", ] [[package]] @@ -153,6 +208,24 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "regex" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", +] + +[[package]] +name = "regex-syntax" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189" + [[package]] name = "strsim" version = "0.8.0" @@ -210,6 +283,15 @@ dependencies = [ "syn", ] +[[package]] +name = "thread_local" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" +dependencies = [ + "lazy_static", +] + [[package]] name = "treeline" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 16cd4b3..0cdc47f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,8 @@ default-features = false features = ["suggestions", "color", "wrap_help"] [dev-dependencies] -assert_cmd = "1.0.1" +assert_cmd = "1.0" +predicates = "1.0" [profile.release] lto = true diff --git a/src/bin/hexyl.rs b/src/bin/hexyl.rs index ca64abd..5243bca 100644 --- a/src/bin/hexyl.rs +++ b/src/bin/hexyl.rs @@ -150,12 +150,20 @@ fn run() -> Result<(), AnyhowError> { let skip_offset = if let Some(ByteOffset { kind, value }) = skip_arg { let value = value.into_inner(); - reader.seek(match kind { - ByteOffsetKind::ForwardFromBeginning | ByteOffsetKind::ForwardFromLastOffset => { - SeekFrom::Current(value) - } - ByteOffsetKind::BackwardFromEnd => SeekFrom::End(value.checked_neg().unwrap()), - })? + reader + .seek(match kind { + ByteOffsetKind::ForwardFromBeginning | ByteOffsetKind::ForwardFromLastOffset => { + SeekFrom::Current(value) + } + ByteOffsetKind::BackwardFromEnd => SeekFrom::End(value.checked_neg().unwrap()), + }) + .map_err(|_| { + anyhow!( + "Failed to jump to the desired input position. \ + This could be caused by a negative offset that is too large or by \ + an input that is not seek-able (e.g. if the input comes from a pipe)." + ) + })? } else { 0 }; diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 2633e01..1ddc0b5 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -84,6 +84,27 @@ fn prints_warning_when_skipping_past_the_end() { ); } +#[test] +fn can_handle_negative_skip_arguments() { + hexyl() + .arg("hello_world_elf64") + .arg("--color=never") + .arg("--skip=-1KiB") + .assert() + .success(); +} + +#[test] +fn fails_if_negative_offset_is_too_large() { + hexyl() + .arg("hello_world_elf64") + .arg("--color=never") + .arg("--skip=-1MiB") + .assert() + .failure() + .stderr(predicates::str::contains("Failed to jump")); +} + #[test] fn fail_if_length_and_bytes_options_are_used_simultaneously() { hexyl()