From 5db090d4d37fc1b3e77f30e68223101c1c70cecb Mon Sep 17 00:00:00 2001 From: merces Date: Sat, 26 Sep 2026 01:11:09 -0300 Subject: [PATCH 01/11] feat(search): replace memchr with yara-x --- Cargo.lock | 1167 ++++++++++++++++++++++++++++++++++++++++++--- Cargo.toml | 2 +- src/hex/events.rs | 8 +- src/hex/search.rs | 116 +++-- 4 files changed, 1169 insertions(+), 124 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d8aaabf..e40dbf7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "addr2line" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59317f77929f0e679d39364702289274de2f0f0b22cbf50b2b8cff2169a0b27a" +dependencies = [ + "gimli 0.33.0", +] + [[package]] name = "aho-corasick" version = "1.1.5" @@ -26,6 +35,17 @@ dependencies = [ "libc", ] +[[package]] +name = "annotate-snippets" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f211a51805bc641f3ad5b7664c77d2547af685cc33b4cd8d31964027a46f13f1" +dependencies = [ + "anstyle", + "memchr", + "unicode-width", +] + [[package]] name = "anstream" version = "1.0.0" @@ -91,6 +111,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + [[package]] name = "arboard" version = "3.6.1" @@ -108,6 +134,23 @@ dependencies = [ "x11rb", ] +[[package]] +name = "ascii_tree" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6c635b3aa665c649ad1415f1573c85957dfa47690ec27aebe7ec17efe3c643" + +[[package]] +name = "async-trait" +version = "0.1.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + [[package]] name = "atomic" version = "0.6.1" @@ -129,6 +172,32 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" + +[[package]] +name = "bincode" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" +dependencies = [ + "bincode_derive", + "serde", + "unty", +] + +[[package]] +name = "bincode_derive" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09" +dependencies = [ + "virtue", +] + [[package]] name = "bit-set" version = "0.5.3" @@ -155,6 +224,22 @@ name = "bitflags" version = "2.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" +dependencies = [ + "serde_core", +] + +[[package]] +name = "bitvec" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddcec3d12c579d40898fe0a9a358a803c23e9c52ca3c425707f81c9436211837" +dependencies = [ + "funty", + "radium", + "serde", + "tap", + "wyz", +] [[package]] name = "block-buffer" @@ -165,11 +250,25 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bstr" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb31b46c14244e20ee9984b11bf5c992b91fb6939fea616e3512c8baecdbe5f" +dependencies = [ + "memchr", + "regex-automata", + "serde_core", +] + [[package]] name = "bumpalo" version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" +dependencies = [ + "allocator-api2", +] [[package]] name = "by_address" @@ -287,6 +386,15 @@ dependencies = [ "error-code", ] +[[package]] +name = "cobs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror 2.0.21", +] + [[package]] name = "colorchoice" version = "1.0.5" @@ -328,6 +436,21 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f8f80099a98041a3d1622845c271458a2d73e688351bf3cb999266764b81d48" +[[package]] +name = "countme" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636" + +[[package]] +name = "cpp_demangle" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2bb79cb74d735044c972aae58ed0aaa9a837e85b01106a54c39e42e97f62253" +dependencies = [ + "cfg-if", +] + [[package]] name = "cpufeatures" version = "0.2.17" @@ -346,12 +469,188 @@ dependencies = [ "libc", ] +[[package]] +name = "cranelift-assembler-x64" +version = "0.132.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d521bdbc6098937af83ef4ab6d5c07398126bc71878f7ef4ea9499977978ef5" +dependencies = [ + "cranelift-assembler-x64-meta", +] + +[[package]] +name = "cranelift-assembler-x64-meta" +version = "0.132.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dde0b83164d4a497860af4236271178bc640512b067101e0853e4f74eaa4df5" +dependencies = [ + "cranelift-srcgen", +] + +[[package]] +name = "cranelift-bforest" +version = "0.132.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0111d110b72b4efad69a372e29e21628652fd0bcab66967e5c8350ab679affd5" +dependencies = [ + "cranelift-entity", + "wasmtime-internal-core", +] + +[[package]] +name = "cranelift-bitset" +version = "0.132.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf01ecc92fc5499789d79c3b817299d5a8ddd828d31dcf0f9cc3cc66f38dbb36" +dependencies = [ + "serde", + "serde_derive", + "wasmtime-internal-core", +] + +[[package]] +name = "cranelift-codegen" +version = "0.132.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cd2563bead0090c3879a7ff7327f7550c9d59bb5d05ecc8cd7886977aa3125a" +dependencies = [ + "bumpalo", + "cranelift-assembler-x64", + "cranelift-bforest", + "cranelift-bitset", + "cranelift-codegen-meta", + "cranelift-codegen-shared", + "cranelift-control", + "cranelift-entity", + "cranelift-isle", + "gimli 0.33.0", + "hashbrown 0.17.1", + "libm", + "log", + "pulley-interpreter", + "regalloc2", + "rustc-hash 2.1.3", + "serde", + "smallvec", + "target-lexicon", + "wasmtime-internal-core", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.132.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9640d250d26f9381a73dc7f9862b27928d4809119aec73be0e556612e67b6a99" +dependencies = [ + "cranelift-assembler-x64-meta", + "cranelift-codegen-shared", + "cranelift-srcgen", + "heck", + "pulley-interpreter", +] + +[[package]] +name = "cranelift-codegen-shared" +version = "0.132.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a07f156b90efc94371ddb3536f76e4ab671ad2e093bfa5511e10198cadbb0c47" + +[[package]] +name = "cranelift-control" +version = "0.132.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a76fd9dd37dcbc3d2d2e00abe3281a7e88adc035fba3b8114cc69981576ec" +dependencies = [ + "arbitrary", +] + +[[package]] +name = "cranelift-entity" +version = "0.132.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eea22522144ba08c7e7ef94bfc25d474ef016c2771974b8ab1986734ac85965" +dependencies = [ + "cranelift-bitset", + "serde", + "serde_derive", + "wasmtime-internal-core", +] + +[[package]] +name = "cranelift-frontend" +version = "0.132.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efa2826c80dff1d93b19b3cfbcaf9fae44c78d739a98d146dd5bd89c51e14367" +dependencies = [ + "cranelift-codegen", + "log", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-isle" +version = "0.132.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e238a69b95c5415456f22189494a12db94f313bb72b6ec9cc88ddf2f1056e28e" + +[[package]] +name = "cranelift-native" +version = "0.132.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eceb0ebd8d6aef6bb287e8d532a164b0db1c0062961211e9c22a91f67521c098" +dependencies = [ + "cranelift-codegen", + "libc", + "target-lexicon", +] + +[[package]] +name = "cranelift-srcgen" +version = "0.132.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "004643f39a7bec553de5263d650db30e5b9caec1d5cbe065fd732b7ec9ae40d0" + +[[package]] +name = "crc32fast" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01a7799fd6b852db0e61728dde9a204c423b44d689dbd432522543614b490e78" +dependencies = [ + "cfg-if", +] + [[package]] name = "critical-section" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" +[[package]] +name = "crossbeam-deque" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622f3fc73690be383c7214310406f28a90e6edeadc3cea882f9d71e495b9711a" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc74980687109a3b14c72fd458107bf0baa1da1a1a805e178d15501ba9b86d9d" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6" + [[package]] name = "crossterm" version = "0.29.0" @@ -381,9 +680,9 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.7" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", "typenum", @@ -399,6 +698,12 @@ dependencies = [ "phf", ] +[[package]] +name = "daachorse" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd10668980c9e7ba8aa2e616207d9ec52f7db66ebb47db857ed1f3c342530dad" + [[package]] name = "darling" version = "0.24.1" @@ -536,7 +841,6 @@ dependencies = [ "evalexpr", "goblin", "hex", - "memchr", "mmap-io", "pretty_assertions", "rand 0.10.3", @@ -546,6 +850,7 @@ dependencies = [ "shell-words", "toml", "tui-input", + "yara-x", ] [[package]] @@ -554,15 +859,26 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34" +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + [[package]] name = "encoding_rs" -version = "0.8.41" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5ef0006ac9ab233c38522f5ae99cae3625151de8f706cacee1cba4b8e2832a" +checksum = "8e985e0451871ad22fb8d2b6b076e2028a502a0d3950998c2c5c0a4f9b5d9679" dependencies = [ "cfg-if", "core_detect", - "multiversion", "multiversion_no_op", "rustversion", "scopeguard", @@ -606,6 +922,12 @@ version = "13.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25929004897f2bbab309121a60400d36992f6d911d09baa6c172f6cc55706601" +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + [[package]] name = "fancy-regex" version = "0.11.0" @@ -657,6 +979,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futures-core" version = "0.3.34" @@ -683,9 +1011,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.7" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" dependencies = [ "typenum", "version_check", @@ -708,8 +1036,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -736,6 +1066,53 @@ dependencies = [ "rand_core 0.10.1", ] +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" +dependencies = [ + "fallible-iterator", + "indexmap", + "stable_deref_trait", +] + +[[package]] +name = "gimli" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf7f043f89559805f8c7cacc432749b2fa0d0a0a9ee46ce47164ed5ba7f126c" +dependencies = [ + "fnv", + "hashbrown 0.16.1", + "indexmap", + "stable_deref_trait", +] + +[[package]] +name = "globset" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07c34a9410465b45bd9787443bc7370f37735bad04b0f0cd57ff1a3186c98988" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "globwalk" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" +dependencies = [ + "bitflags 2.13.2", + "ignore", + "walkdir", +] + [[package]] name = "goblin" version = "0.10.7" @@ -747,6 +1124,12 @@ dependencies = [ "scroll", ] +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + [[package]] name = "hashbrown" version = "0.16.1" @@ -756,6 +1139,8 @@ dependencies = [ "allocator-api2", "equivalent", "foldhash", + "serde", + "serde_core", ] [[package]] @@ -767,6 +1152,8 @@ dependencies = [ "allocator-api2", "equivalent", "foldhash", + "serde", + "serde_core", ] [[package]] @@ -805,12 +1192,34 @@ dependencies = [ "cc", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "ident_case" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "ignore" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b69833ed729dc5aa7d19541d96d6cf8e9137194207a04916d658e43168402f" +dependencies = [ + "crossbeam-deque", + "globset", + "log", + "memchr", + "regex-automata", + "same-file", + "walkdir", + "winapi-util", +] + [[package]] name = "indexmap" version = "2.14.2" @@ -819,6 +1228,8 @@ checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" dependencies = [ "equivalent", "hashbrown 0.17.1", + "serde", + "serde_core", ] [[package]] @@ -832,9 +1243,9 @@ dependencies = [ [[package]] name = "instability" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bf84e73fa6f27f299dec58e13223cf70db80da872eb921d4f6138342a0eabc8" +checksum = "4c3b5acc1e2fd9375041a388da33d1eb8aed5f7a8c0dd3543e3ea2805adfbe20" dependencies = [ "darling", "indoc", @@ -843,6 +1254,21 @@ dependencies = [ "syn 3.0.6", ] +[[package]] +name = "intaglio" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eca9188c1b20836bb561bc09bb2f54e9ca99b271031b5f3ff183a00c08c98c8" + +[[package]] +name = "inventory" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4f0c30c76f2f4ccee3fe55a2435f691ca00c0e4bd87abe4f4a851b1d4dac39b" +dependencies = [ + "rustversion", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -858,6 +1284,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b4baf93f58d4425749ca49a51c50ebab072c5df6994d08fed93541c331481dc" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.18" @@ -883,7 +1318,7 @@ checksum = "bde5057d6143cc94e861d90f591b9303d6716c6b9602309150bd068853c10899" dependencies = [ "hashbrown 0.16.1", "portable-atomic", - "thiserror 2.0.20", + "thiserror 2.0.21", ] [[package]] @@ -898,6 +1333,18 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "leb128" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c83bff1d572d6b9aeef67ddfc8448e4a3737909cb28e81f97c791b9018703e52" + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "libc" version = "0.2.189" @@ -912,9 +1359,9 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6480ccc157a1389bb2e4891b24751b0f798ba640d22386f23143fbcc89da195a" +checksum = "61ff90caf6077a803a240f62fdbe88645a890bbca49ef8174c3cb0404362171d" dependencies = [ "libc", ] @@ -955,11 +1402,43 @@ version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" +[[package]] +name = "logos" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb2c55a318a87600ea870ff8c2012148b44bf18b74fad48d0f835c38c7d07c5f" +dependencies = [ + "logos-derive", +] + +[[package]] +name = "logos-codegen" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58b3ffaa284e1350d017a57d04ada118c4583cf260c8fb01e0fe28a2e9cf8970" +dependencies = [ + "fnv", + "proc-macro2", + "quote", + "regex-automata", + "regex-syntax", + "syn 2.0.119", +] + +[[package]] +name = "logos-derive" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52d3a9855747c17eaf4383823f135220716ab49bea5fbea7dd42cc9a92f8aa31" +dependencies = [ + "logos-codegen", +] + [[package]] name = "lru" -version = "0.18.4" +version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff9840bcc50b71349309900da0ce7279aa336ae71d73250b07998932c7d97c25" +checksum = "ef9ac18847474e638e3702b76c65d4eb93428471a74778ef0f1be711717f89b5" dependencies = [ "hashbrown 0.17.1", ] @@ -974,12 +1453,30 @@ dependencies = [ "winapi", ] +[[package]] +name = "mach2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" +dependencies = [ + "libc", +] + [[package]] name = "memchr" version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" +[[package]] +name = "memfd" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57804b2c9b69967f1536a56f86297e367a33b19e98852ed624b84551cdbc0d90" +dependencies = [ + "rustix", +] + [[package]] name = "memmap2" version = "0.7.1" @@ -989,6 +1486,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memmap2" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0" +dependencies = [ + "libc", +] + [[package]] name = "memmem" version = "0.1.1" @@ -1032,32 +1538,11 @@ dependencies = [ "cfg-if", "libc", "log", - "memmap2", + "memmap2 0.7.1", "parking_lot", "thiserror 1.0.69", ] -[[package]] -name = "multiversion" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ca4bea16ffc3f443cf7d866912118196bfef4c6a1556ca00f9f9b00bb43f7c" -dependencies = [ - "multiversion-macros", -] - -[[package]] -name = "multiversion-macros" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d416831a7317ef4b08bee00b69cbbb9c8763da7959a7026244d6266869f9c83" -dependencies = [ - "proc-macro2", - "quote", - "rustversion", - "syn 3.0.6", -] - [[package]] name = "multiversion_no_op" version = "1.0.0" @@ -1195,6 +1680,18 @@ dependencies = [ "objc2-core-foundation", ] +[[package]] +name = "object" +version = "0.39.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e5a6c098c7a3b6547378093f5cc30bc54fd361ce711e05293a5cc589562739b" +dependencies = [ + "crc32fast", + "hashbrown 0.17.1", + "indexmap", + "memchr", +] + [[package]] name = "once_cell" version = "1.21.4" @@ -1280,9 +1777,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d45aeb61b4bf818e12d4205f2466f8c4748f85f4fce0146d1c03d69d753f0ad" +checksum = "45d3aca230fad2e6f6317ca0a72724338c4960cb97168a85cdee66df4a9a21a8" dependencies = [ "memchr", "ucd-trie", @@ -1290,9 +1787,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89cc5a242e25ed4e7704d0be240f2cfbe20a8c27e7e252d94835be93d92dc39f" +checksum = "284b60557f2c4a2e72ad3f2d34d42685a2fa4a6a61d0d2a10c0ae2a5e916c2cf" dependencies = [ "pest", "pest_generator", @@ -1300,9 +1797,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abf21475cc3820fe4b2ca2dc2142902f67a02189f3b5b3a229f4febc01a43e5" +checksum = "1d9d1f08a115309ee99268cf85e5228e0e56aa9caf8841ec12866b6be07c3109" dependencies = [ "pest", "pest_meta", @@ -1313,9 +1810,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adba4db388f687393c18c51348d44a41d870ca9df71a2c98172ea3035dc6936e" +checksum = "ed93ba1a9ffcca32130a5188701c81c0c49cf00d4b7c5007d5148951d743adcb" dependencies = [ "pest", ] @@ -1390,6 +1887,18 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" +[[package]] +name = "postcard" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" +dependencies = [ + "cobs", + "embedded-io 0.4.0", + "embedded-io 0.6.1", + "serde", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -1415,6 +1924,49 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "protobuf" +version = "3.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d65a1d4ddae7d8b5de68153b48f6aa3bba8cb002b243dbdbc55a5afbc98f99f4" +dependencies = [ + "once_cell", + "protobuf-support", + "thiserror 1.0.69", +] + +[[package]] +name = "protobuf-support" +version = "3.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e36c2f31e0a47f9280fb347ef5e461ffcd2c52dd520d8e216b52f93b0b0d7d6" +dependencies = [ + "thiserror 1.0.69", +] + +[[package]] +name = "pulley-interpreter" +version = "45.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b04adf8f93264685f2c70a3edb8f828c791e71b22659253319c33f29d1165aef" +dependencies = [ + "cranelift-bitset", + "log", + "pulley-macros", + "wasmtime-internal-core", +] + +[[package]] +name = "pulley-macros" +version = "45.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c120a6af1a574a42efcd9df2ad27cb78bc04118c5e0c69e90599f17301a1c7a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "quote" version = "1.0.47" @@ -1436,6 +1988,12 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.8.8" @@ -1494,13 +2052,13 @@ dependencies = [ "compact_str", "critical-section", "hashbrown 0.17.1", - "itertools", + "itertools 0.14.0", "kasuari", "lru", "palette", "serde", "strum", - "thiserror 2.0.20", + "thiserror 2.0.21", "unicode-segmentation", "unicode-truncate", "unicode-width", @@ -1559,7 +2117,7 @@ dependencies = [ "hashbrown 0.17.1", "indoc", "instability", - "itertools", + "itertools 0.14.0", "line-clipping", "ratatui-core", "serde", @@ -1589,6 +2147,20 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "regalloc2" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "757712e8e61590d6d4f5d563483755538b5aa13467837a3b41cd9832509a7f85" +dependencies = [ + "allocator-api2", + "bumpalo", + "hashbrown 0.17.1", + "log", + "rustc-hash 2.1.3", + "smallvec", +] + [[package]] name = "regex" version = "1.13.1" @@ -1602,21 +2174,52 @@ dependencies = [ ] [[package]] -name = "regex-automata" -version = "0.4.18" +name = "regex-automata" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "rowan" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14b574c58582fa59fa43a2feb6608b8744184659f08a2e0117e4b8224d95ed61" +dependencies = [ + "countme", + "hashbrown 0.14.5", + "memoffset", + "rustc-hash 1.1.0", + "text-size", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b74b56ffa8bb2830709a538c2cbcae9aa062db0d2a42563bfb09bdaae44020eb" + +[[package]] +name = "rustc-hash" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] -name = "regex-syntax" -version = "0.8.11" +name = "rustc-hash" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" [[package]] name = "rustc_version" @@ -1652,6 +2255,15 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -1714,6 +2326,20 @@ dependencies = [ "syn 3.0.6", ] +[[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "indexmap", + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + [[package]] name = "serde_spanned" version = "1.1.1" @@ -1797,9 +2423,18 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.16.1" +version = "1.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9395f0f0eee849a9b707b2f06bb92a6a422090e2123bb2ef8e87a0e61892a8e" +dependencies = [ + "serde", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba467056f1b547ed52077911161fc86985becbc60e8e1857c8a144dab0def891" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "static_assertions" @@ -1867,6 +2502,27 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "target-lexicon" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "termina" version = "0.3.3" @@ -1908,7 +2564,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4676b37242ccbd1aabf56edb093a4827dc49086c0ffd764a5705899e0f35f8f7" dependencies = [ "anyhow", - "base64", + "base64 0.22.1", "bitflags 2.13.2", "fancy-regex", "filedescriptor", @@ -1943,6 +2599,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "text-size" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233" + [[package]] name = "thiserror" version = "1.0.69" @@ -1954,11 +2616,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.20" +version = "2.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e" dependencies = [ - "thiserror-impl 2.0.20", + "thiserror-impl 2.0.21", ] [[package]] @@ -1974,9 +2636,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.20" +version = "2.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" dependencies = [ "proc-macro2", "quote", @@ -2084,7 +2746,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16b380a1238663e5f8a691f9039c73e1cdae598a30e9855f541d29b08b53e9a5" dependencies = [ - "itertools", + "itertools 0.14.0", "unicode-segmentation", "unicode-width", ] @@ -2095,6 +2757,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" +[[package]] +name = "unty" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" + [[package]] name = "utf8parse" version = "0.2.2" @@ -2119,6 +2787,12 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "virtue" +version = "0.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1" + [[package]] name = "vtparse" version = "0.6.2" @@ -2128,6 +2802,44 @@ dependencies = [ "utf8parse", ] +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "walrus" +version = "0.26.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b63a2bc6e4acb4cf69080068a531bad4530791098230e972ffcb64fd1dc266" +dependencies = [ + "anyhow", + "gimli 0.32.3", + "id-arena", + "leb128", + "log", + "walrus-macro", + "wasm-encoder 0.245.1", + "wasmparser 0.245.1", +] + +[[package]] +name = "walrus-macro" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a9b0525d7ea6e5f906aca581a172e5c91b4c595290dfa8ad4a2bc9ffef33b44" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -2188,6 +2900,228 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.245.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9dca005e69bf015e45577e415b9af8c67e8ee3c0e38b5b0add5aa92581ed5c" +dependencies = [ + "leb128fmt", + "wasmparser 0.245.1", +] + +[[package]] +name = "wasm-encoder" +version = "0.248.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac92cf547bc18d27ecc521015c08c353b4f18b84ab388bb6d1b6b682c620d9b6" +dependencies = [ + "leb128fmt", + "wasmparser 0.248.0", +] + +[[package]] +name = "wasmparser" +version = "0.245.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f08c9adee0428b7bddf3890fc27e015ac4b761cc608c822667102b8bfd6995e" +dependencies = [ + "bitflags 2.13.2", + "hashbrown 0.16.1", + "indexmap", + "semver", + "serde", +] + +[[package]] +name = "wasmparser" +version = "0.248.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa4439c5eee9df71ee0c6efb37f63b1fcb1fec38f85f5142c54e7ed05d33091a" +dependencies = [ + "bitflags 2.13.2", + "hashbrown 0.17.1", + "indexmap", + "semver", + "serde", +] + +[[package]] +name = "wasmprinter" +version = "0.248.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b264a5410b008d4d199a92bf536eae703cbd614482fc1ec53831cf19e1c183" +dependencies = [ + "anyhow", + "termcolor", + "wasmparser 0.248.0", +] + +[[package]] +name = "wasmtime" +version = "45.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a83ef84ac8bab735c89e27b0268b0586099fbe81281ae45be2b8e4f407b2daa" +dependencies = [ + "addr2line", + "async-trait", + "bitflags 2.13.2", + "bumpalo", + "cc", + "cfg-if", + "libc", + "log", + "mach2", + "memfd", + "object", + "once_cell", + "postcard", + "pulley-interpreter", + "rustix", + "serde", + "serde_derive", + "smallvec", + "target-lexicon", + "wasmparser 0.248.0", + "wasmtime-environ", + "wasmtime-internal-core", + "wasmtime-internal-cranelift", + "wasmtime-internal-fiber", + "wasmtime-internal-jit-debug", + "wasmtime-internal-jit-icache-coherence", + "wasmtime-internal-unwinder", + "wasmtime-internal-versioned-export-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "wasmtime-environ" +version = "45.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439686d3deb38525c86b88bbc90f7ba669f70c8edc7d6b35147c738bbef5ff76" +dependencies = [ + "anyhow", + "cpp_demangle", + "cranelift-bforest", + "cranelift-bitset", + "cranelift-entity", + "gimli 0.33.0", + "hashbrown 0.17.1", + "indexmap", + "log", + "object", + "postcard", + "rustc-demangle", + "serde", + "serde_derive", + "sha2", + "smallvec", + "target-lexicon", + "wasm-encoder 0.248.0", + "wasmparser 0.248.0", + "wasmprinter", + "wasmtime-internal-core", +] + +[[package]] +name = "wasmtime-internal-core" +version = "45.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3073c03f97f871fe6400e68621c863b93ba79296f8e570285231952d23fcc804" +dependencies = [ + "hashbrown 0.17.1", + "libm", + "serde", +] + +[[package]] +name = "wasmtime-internal-cranelift" +version = "45.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a15981261d361f9c93b42929f446b4009840853ceea181ad6e17730f4016a0b" +dependencies = [ + "cfg-if", + "cranelift-codegen", + "cranelift-control", + "cranelift-entity", + "cranelift-frontend", + "cranelift-native", + "gimli 0.33.0", + "itertools 0.14.0", + "log", + "object", + "pulley-interpreter", + "smallvec", + "target-lexicon", + "thiserror 2.0.21", + "wasmparser 0.248.0", + "wasmtime-environ", + "wasmtime-internal-core", + "wasmtime-internal-unwinder", + "wasmtime-internal-versioned-export-macros", +] + +[[package]] +name = "wasmtime-internal-fiber" +version = "45.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33aed9d91d54c9f861ba7e3c3130bded8a7a63e01fe58c3a9a36b45d6ee0fb57" +dependencies = [ + "cc", + "cfg-if", + "libc", + "rustix", + "wasmtime-environ", + "wasmtime-internal-versioned-export-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "wasmtime-internal-jit-debug" +version = "45.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "944942118aab67e7b4febfe88a65d0af4cfd10af8ed0e79fd6cf39d75359ab7e" +dependencies = [ + "cc", + "wasmtime-internal-versioned-export-macros", +] + +[[package]] +name = "wasmtime-internal-jit-icache-coherence" +version = "45.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37dee05e8c35759826f6b926cd949c51f771b6a58619d8e60c63c3f3d3e5e59b" +dependencies = [ + "cfg-if", + "libc", + "wasmtime-internal-core", + "windows-sys 0.61.2", +] + +[[package]] +name = "wasmtime-internal-unwinder" +version = "45.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a83f7ebe911a6f1605ff0d3a678472ddb1fcc57c3e2f6bae5dd4d170b625b3ed" +dependencies = [ + "cfg-if", + "cranelift-codegen", + "log", + "object", + "wasmtime-environ", +] + +[[package]] +name = "wasmtime-internal-versioned-export-macros" +version = "45.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75980644456dc003238766254b0e5f002704630237ccd0728747991fe2739d7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "wezterm-bidi" version = "0.2.3" @@ -2276,6 +3210,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -2436,6 +3379,15 @@ version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "x11rb" version = "0.13.2" @@ -2458,3 +3410,82 @@ name = "yansi" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + +[[package]] +name = "yara-x" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "015b06cc60800856d04c3115ef6b7c6cbb95f59f20a9df4358dd2f85f3d5b391" +dependencies = [ + "annotate-snippets", + "anyhow", + "base64 0.23.1", + "bincode", + "bitflags 2.13.2", + "bitvec", + "bstr", + "daachorse", + "getrandom 0.2.17", + "globwalk", + "hex", + "indexmap", + "intaglio", + "inventory", + "itertools 0.15.0", + "js-sys", + "memchr", + "memmap2 0.9.11", + "num-derive", + "num-traits", + "protobuf", + "regex", + "regex-automata", + "regex-syntax", + "rustc-hash 2.1.3", + "serde", + "serde_json", + "smallvec", + "strum_macros", + "thiserror 2.0.21", + "walrus", + "wasm-bindgen", + "wasmtime", + "yara-x-macros", + "yara-x-parser", +] + +[[package]] +name = "yara-x-macros" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a120badca58e15c6cebaff85386c23b75c31f78c06ccb68d24bd7a27293563ed" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "yara-x-parser" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20ace34cd6497968bfcb513c7bc2c3712b559e3fd1332f81ae49593da88cc5c" +dependencies = [ + "ascii_tree", + "bitflags 2.13.2", + "bstr", + "indexmap", + "itertools 0.15.0", + "logos", + "num-traits", + "rowan", + "rustc-hash 2.1.3", + "serde", +] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/Cargo.toml b/Cargo.toml index a15a3d6..bea718b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,6 @@ encoding_rs = "0.8.35" evalexpr = "13.1.*" goblin = "0.10.5" hex = "0.4.3" -memchr = "2.8.0" mmap-io = "1.0.0" rand = "0.10.1" ratatui = "0.30.0" @@ -29,6 +28,7 @@ serde = { version = "1.0.228", features = ["derive"] } shell-words = "1.1.0" toml = "1.0.1" tui-input = "0.15.0" +yara-x = { version = "1.20.0", default-features = false } # The profile that 'dist' will build with [profile.dist] diff --git a/src/hex/events.rs b/src/hex/events.rs index 85c5c22..b570ed7 100644 --- a/src/hex/events.rs +++ b/src/hex/events.rs @@ -38,19 +38,19 @@ pub fn hex_mode_events(app: &mut App, key: KeyEvent) -> Result { && !app.hex_view.search.input_text.value().is_empty() { let needle = app.hex_view.search.input_text.value().to_string(); - ofs = hex::search::search(app, needle); + ofs = hex::search::search_yr(app, &needle); } else if app.hex_view.search.mode == hex::search::SearchMode::Hex && !app.hex_view.search.input_hex.value().is_empty() { let hex_string = app.hex_view.search.input_hex.value().to_string(); - if let Some(by) = hex::search::hex_string_to_u8(&hex_string) { - ofs = hex::search::search(app, &by) - } + ofs = hex::search::search_yr(app, &hex_string) } if let Some(ofs) = ofs { app.goto(ofs); + } else { + beep!(); } } } diff --git a/src/hex/search.rs b/src/hex/search.rs index 04f71df..57251b5 100644 --- a/src/hex/search.rs +++ b/src/hex/search.rs @@ -1,11 +1,13 @@ use crate::widgets::{Message, MessageType}; use crate::{app::App, editor::UIState}; -use ratatui::Frame; + use ratatui::crossterm::event::{Event, KeyCode}; +use ratatui::Frame; use ratatui::widgets::Paragraph; use std::io::Result; -use tui_input::Input; use tui_input::backend::crossterm::EventHandler; +use tui_input::Input; +use yara_x; #[derive(Default, Debug)] pub struct Search { @@ -41,57 +43,60 @@ pub enum SearchDirection { Backward, } -pub fn hex_string_to_u8(hex_string: &str) -> Option> { - if hex_string.is_empty() || !hex_string.len().is_multiple_of(2) { +pub fn search_yr(app: &mut App, pattern: &str) -> Option { + if pattern.is_empty() { return None; } - let bytes = hex::decode(hex_string).unwrap(); - Some(bytes) -} -pub fn search>(app: &mut App, needle: T) -> Option { - let text = needle.as_ref(); - let filesize = app.file_info.size; - let buffer = app.file_info.get_buffer(); + let string_decl = match app.hex_view.search.mode { + SearchMode::Utf8 => format!("$a = \"{pattern}\" ascii wide nocase"), + SearchMode::Hex => format!("$a = {{{pattern}}}"), + }; - if filesize == 0 || text.is_empty() { - return None; - } + let rule = format!( + r#" + rule dz6 {{ + strings: + {string_decl} + condition: + $a + }}"# + ); + + let rules = yara_x::compile(&*rule).ok()?; + let mut scanner = yara_x::Scanner::new(&rules); + let buffer = app.file_info.get_buffer(); - let ofs = if app.hex_view.search.direction == SearchDirection::Forward { + if app.hex_view.search.direction == SearchDirection::Forward { let start = app.hex_view.offset.checked_add(1)?; - if start < filesize { - memchr::memmem::find(buffer.get(start..)?, text).map(|pos| start + pos) - } else { - None - } - } else { - let end = app.hex_view.offset; - if end > 0 { - memchr::memmem::rfind(buffer.get(..end)?, text) - } else { - None - } - }; + let slice = buffer.get(start..)?; - if ofs.is_some() { - return ofs; - } + // enable fast scan to return the first result only + scanner.fast_scan(true); - // ofs is None, check wrap setting - if app.config.search_wrap { - let ofs = if app.hex_view.search.direction == SearchDirection::Forward { - memchr::memmem::find(buffer, text) - } else { - memchr::memmem::rfind(buffer, text) - }; + let result = scanner.scan(slice).unwrap(); + let rule = result.matching_rules().next()?; + let pattern = rule.patterns().next()?; - if ofs.is_some() { - return ofs; + if let Some(r#match) = pattern.matches().next() { + // the search result is an offset from start, so we add start to it + return r#match.range().start.checked_add(start); + } + } else { + // backward search + // this works, but fast_scan is not set, thus the scanner will + // find all matches so we can get the last one + let slice = buffer.get(..app.hex_view.offset)?; + let result = scanner.scan(slice).unwrap(); + let rule = result.matching_rules().next()?; + let pattern = rule.patterns().next()?; + + // get the last match + if let Some(r#match) = pattern.matches().last() { + return Some(r#match.range().start); } } - crate::beep!(); None } @@ -164,24 +169,30 @@ pub fn dialog_search_events(app: &mut App, event: &Event) -> Result { return Ok(false); } - if let Some(ofs) = search(app, &text) { + if let Some(ofs) = search_yr(app, &text) { app.goto(ofs); app.dialog_renderer = None; } else { app.dialog_renderer = Some(dialog_search_error_draw); + crate::beep!(); } } SearchMode::Hex => { + app.state = UIState::Normal; + let hex_string = app.hex_view.search.input_hex.value().to_string(); - if let Some(bytes) = hex_string_to_u8(&hex_string) { - if let Some(ofs) = search(app, &bytes) { - app.goto(ofs); - app.dialog_renderer = None; - } else { - app.dialog_renderer = Some(dialog_search_error_draw); - } - app.state = UIState::Normal; + if hex_string.is_empty() { + app.dialog_renderer = None; + return Ok(false); + } + + if let Some(ofs) = search_yr(app, &hex_string) { + app.goto(ofs); + app.dialog_renderer = None; + } else { + app.dialog_renderer = Some(dialog_search_error_draw); + crate::beep!(); } } }; @@ -194,7 +205,10 @@ pub fn dialog_search_events(app: &mut App, event: &Event) -> Result { match app.hex_view.search.mode { SearchMode::Utf8 => app.hex_view.search.input_text.handle_event(event), SearchMode::Hex => { - if c.is_ascii_hexdigit() { + // as per https://virustotal.github.io/yara-x/docs/writing_rules/hex-patterns/ + let allowed = [' ', '?', '[', '-', ']', 'x', 'X', '~', '(', ')', '|']; + + if c.is_ascii_hexdigit() || allowed.contains(&c) { app.hex_view.search.input_hex.handle_event(event) } else { None From 1db0f6d47c70ff51b93ed485583242a3465eb206 Mon Sep 17 00:00:00 2001 From: merces Date: Sun, 27 Sep 2026 00:42:49 -0300 Subject: [PATCH 02/11] feat: search wrap --- src/hex/search.rs | 47 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/src/hex/search.rs b/src/hex/search.rs index 57251b5..7bf17c1 100644 --- a/src/hex/search.rs +++ b/src/hex/search.rs @@ -1,12 +1,12 @@ use crate::widgets::{Message, MessageType}; use crate::{app::App, editor::UIState}; -use ratatui::crossterm::event::{Event, KeyCode}; use ratatui::Frame; +use ratatui::crossterm::event::{Event, KeyCode}; use ratatui::widgets::Paragraph; use std::io::Result; -use tui_input::backend::crossterm::EventHandler; use tui_input::Input; +use tui_input::backend::crossterm::EventHandler; use yara_x; #[derive(Default, Debug)] @@ -75,12 +75,27 @@ pub fn search_yr(app: &mut App, pattern: &str) -> Option { scanner.fast_scan(true); let result = scanner.scan(slice).unwrap(); - let rule = result.matching_rules().next()?; - let pattern = rule.patterns().next()?; - if let Some(r#match) = pattern.matches().next() { - // the search result is an offset from start, so we add start to it - return r#match.range().start.checked_add(start); + // if we're at the end, the rule won't match... + if let Some(rule) = result.matching_rules().next() { + // na segunda vez n tem matching rule + + let pattern = rule.patterns().next()?; + + if let Some(r#match) = pattern.matches().next() { + // the search result is an offset from start, so we add start to it + return r#match.range().start.checked_add(start); + } + // ...so we check if wrapscan is set to try again from the beginning + } else if app.config.search_wrap { + let start = 0; + let slice = buffer.get(start..)?; + let result = scanner.scan(slice).unwrap(); + let rule = result.matching_rules().next()?; + let pattern = rule.patterns().next()?; + let r#match = pattern.matches().next()?; + + return Some(r#match.range().start); } } else { // backward search @@ -88,11 +103,21 @@ pub fn search_yr(app: &mut App, pattern: &str) -> Option { // find all matches so we can get the last one let slice = buffer.get(..app.hex_view.offset)?; let result = scanner.scan(slice).unwrap(); - let rule = result.matching_rules().next()?; - let pattern = rule.patterns().next()?; - // get the last match - if let Some(r#match) = pattern.matches().last() { + if let Some(rule) = result.matching_rules().next() { + let pattern = rule.patterns().next()?; + + // get the last match + if let Some(r#match) = pattern.matches().last() { + return Some(r#match.range().start); + } + } else if app.config.search_wrap { + let slice = buffer.get(0..)?; + let result = scanner.scan(slice).unwrap(); + let rule = result.matching_rules().next()?; + let pattern = rule.patterns().next()?; + let r#match = pattern.matches().last()?; + return Some(r#match.range().start); } } From 8115d94780ddb738c98d602376d326ed472d5fca Mon Sep 17 00:00:00 2001 From: merces Date: Sun, 27 Sep 2026 00:43:14 -0300 Subject: [PATCH 03/11] feat: search wrap true by default --- src/app.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app.rs b/src/app.rs index 74ac231..220a783 100644 --- a/src/app.rs +++ b/src/app.rs @@ -104,7 +104,7 @@ impl App { hex_mode_non_graphic_char: '.', maximum_strings_to_show: 3000, minimum_string_length: 4, - search_wrap: true, + search_wrap: false, theme: DARK, // hex_mode_dword_separator: '-', // text_mode_tab_spaces: 4, From 8d47961041019370425d8c0e55a2e56edeab487d Mon Sep 17 00:00:00 2001 From: merces Date: Sun, 4 Oct 2026 07:03:16 -0300 Subject: [PATCH 04/11] feat: add options to control string search --- src/app.rs | 4 +++- src/commands.rs | 30 +++++++++++++++++++++++++----- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/app.rs b/src/app.rs index 220a783..8198a61 100644 --- a/src/app.rs +++ b/src/app.rs @@ -104,7 +104,9 @@ impl App { hex_mode_non_graphic_char: '.', maximum_strings_to_show: 3000, minimum_string_length: 4, - search_wrap: false, + search_wrapscan: false, + search_ignorecase: false, + search_smartcase: false, theme: DARK, // hex_mode_dword_separator: '-', // text_mode_tab_spaces: 4, diff --git a/src/commands.rs b/src/commands.rs index 99030fd..9575a1c 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -235,13 +235,33 @@ pub fn parse_command(app: &mut App, cmdline: &str) { } } } - // saarch wrap - "wrapscan" => { - app.config.search_wrap = true; + // search wrap + "wrapscan" | "ws" => { + app.config.search_wrapscan = true; app.dialog_renderer = None; } - "nowrapscan" => { - app.config.search_wrap = false; + "nowrapscan" | "nows" => { + app.config.search_wrapscan = false; + app.dialog_renderer = None; + } + // search ignorecase + "ignorecase" | "ic" => { + app.config.search_ignorecase = true; + app.dialog_renderer = None; + } + "noignorecase" | "noic" => { + app.config.search_ignorecase = false; + app.dialog_renderer = None; + } + // search smartcase + // if ignorecase == true and needle contains a capital letter, + // then ignorecase will be set to false + "smartcase" | "scs" => { + app.config.search_smartcase = true; + app.dialog_renderer = None; + } + "nosmartcase" | "noscs" => { + app.config.search_smartcase = false; app.dialog_renderer = None; } // view From 9fb2e958f07246674bc9c2414bcc3057b5a99b66 Mon Sep 17 00:00:00 2001 From: merces Date: Sun, 4 Oct 2026 07:03:47 -0300 Subject: [PATCH 05/11] feat: add config options --- src/config.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/config.rs b/src/config.rs index 72d6846..09a4156 100644 --- a/src/config.rs +++ b/src/config.rs @@ -13,7 +13,9 @@ pub struct Config { pub hex_mode_non_graphic_char: char, pub maximum_strings_to_show: usize, pub minimum_string_length: usize, - pub search_wrap: bool, + pub search_wrapscan: bool, + pub search_ignorecase: bool, + pub search_smartcase: bool, pub theme: Theme, // pub hex_mode_dword_separator: char, // pub text_mode_tab_spaces: usize, From 0fa7bc037faac6c17362f574aeb3cfcf26f28546 Mon Sep 17 00:00:00 2001 From: merces Date: Sun, 4 Oct 2026 07:12:01 -0300 Subject: [PATCH 06/11] feat: case-insensitive ASCII search uses memchr instead of yara-x --- Cargo.lock | 45 ++++---- Cargo.toml | 1 + src/hex/events.rs | 5 +- src/hex/search.rs | 258 +++++++++++++++++++++++++++++++++++++++------- 4 files changed, 245 insertions(+), 64 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e40dbf7..5b78ef8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -293,9 +293,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.4.7" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54413ede23c2daf518f35156dfde027feb2374004d63bd497f983c8db9c0e313" +checksum = "f360145194ee8e21db5ee7f3fcd4fe52210864c75c985dae33218202c8bbe040" dependencies = [ "find-msvc-tools", "shlex", @@ -680,9 +680,9 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "typenum", @@ -841,6 +841,7 @@ dependencies = [ "evalexpr", "goblin", "hex", + "memchr", "mmap-io", "pretty_assertions", "rand 0.10.3", @@ -951,9 +952,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef25905e51abafe4dcea6c15fec58c57b601cdbd0ee53d22ea1d3016c587d39b" +checksum = "aedcfb3409746eddb02b9e19ebda1c3394f759a152e48ee875a0844d1b955484" [[package]] name = "finl_unicode" @@ -1011,9 +1012,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.9" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", @@ -1301,9 +1302,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.105" +version = "0.3.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce57d20d1ea864ce2ac172ab472d409214f4fd359f0b2a2775abdf522e2af99e" +checksum = "7883d941dae510fb2d978fc3fe018c71c9e2892fd38854de3e8b92c2e5ad9cc5" dependencies = [ "cfg-if", "futures-util", @@ -2411,9 +2412,9 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "siphasher" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" +checksum = "33f4fe9184a62d842c9ef383018f3306d8ba224fd9d836f56d7288308847c256" [[package]] name = "slab" @@ -2707,9 +2708,9 @@ checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" [[package]] name = "tui-input" -version = "0.15.4" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb7c7ddaef6dcc58fae905d0f89a3df49ef77e93822df7447a5bb0babc9ece3" +checksum = "a4fa0cb7933d19f91eb3109781bf7297d5e4cba57e857d97a29b9465d3383f56" dependencies = [ "ratatui", "unicode-segmentation", @@ -2857,9 +2858,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.128" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aecb87a33d3b0c5e3b7aa46336eaf486cffafbd281b195e4c8b80d50df2351bf" +checksum = "9bb54f33acc68fd454578d9820b0bde1a1a3d17aa17bb7b6595806d02886d409" dependencies = [ "cfg-if", "once_cell", @@ -2870,9 +2871,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.128" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a690d511e3c1a8b3a55e33511e3c2c00c78415cd23650f32b808627f5696b9ed" +checksum = "2e29d0c35b16e224a7eeb5cd2d25e3e1968fbd65604117b44d3b789d00ee8535" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2880,9 +2881,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.128" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "411e4887f0071ef2d2164a9d5fdf2d20efbef78fccd3a78b0c10a1dc5295e48a" +checksum = "6f501a8bc3719dba86ef8ae4728879c08001bea749eb1333ac5b91e040e2a6b7" dependencies = [ "bumpalo", "proc-macro2", @@ -2893,9 +2894,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.128" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81941cd78d0c92026c33e5e01312845a4cb1e9af3407f9134b100dd03144103e" +checksum = "23f0c9c52aa7cd7d77769a4cfe2a9adb1b331f489a41d912ce14513d5ab995c6" dependencies = [ "unicode-ident", ] diff --git a/Cargo.toml b/Cargo.toml index bea718b..149ed66 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ encoding_rs = "0.8.35" evalexpr = "13.1.*" goblin = "0.10.5" hex = "0.4.3" +memchr = "2.8.3" mmap-io = "1.0.0" rand = "0.10.1" ratatui = "0.30.0" diff --git a/src/hex/events.rs b/src/hex/events.rs index b570ed7..f292387 100644 --- a/src/hex/events.rs +++ b/src/hex/events.rs @@ -38,13 +38,14 @@ pub fn hex_mode_events(app: &mut App, key: KeyEvent) -> Result { && !app.hex_view.search.input_text.value().is_empty() { let needle = app.hex_view.search.input_text.value().to_string(); - ofs = hex::search::search_yr(app, &needle); + + ofs = hex::search::search(app, &needle, true); } else if app.hex_view.search.mode == hex::search::SearchMode::Hex && !app.hex_view.search.input_hex.value().is_empty() { let hex_string = app.hex_view.search.input_hex.value().to_string(); - ofs = hex::search::search_yr(app, &hex_string) + ofs = hex::search::search(app, &hex_string, true) } if let Some(ofs) = ofs { diff --git a/src/hex/search.rs b/src/hex/search.rs index 7bf17c1..096f1a6 100644 --- a/src/hex/search.rs +++ b/src/hex/search.rs @@ -43,13 +43,160 @@ pub enum SearchDirection { Backward, } -pub fn search_yr(app: &mut App, pattern: &str) -> Option { +fn hex_string_to_u8(hex_string: &str) -> Option> { + if hex_string.is_empty() || !hex_string.len().is_multiple_of(2) { + return None; + } + let bytes = hex::decode(hex_string).unwrap(); + Some(bytes) +} + +/// returns the fist occurrence of needle, ignoring case (ASCII only for now) +/// so, it won't work with utf-8 characters for example +fn find_nocase(haystack: &[u8], needle: &[u8]) -> Option { + // get first needle char and return early if we can't / needle.len() == 0 + let first = needle.first()?; + let needle_len = needle.len(); + + // we can't search for a needle bigger than the haystack + if needle_len > haystack.len() { + return None; + } + + if first.is_ascii_alphabetic() { + // if needle's first letter is alphabetic, we use memchr2_iter to find both variants + for pos in memchr::memchr2_iter( + first.to_ascii_lowercase(), + first.to_ascii_uppercase(), + haystack, + ) { + let mut matches = 1; // number of matching characters + + for c in needle.iter().skip(1) { + if !c.eq_ignore_ascii_case(haystack.get(pos + matches)?) { + break; + } + + matches += 1; + } + + if matches == needle_len { + return Some(pos); + } + } + } else { + // otherwise we call memchr_iter, which is faster + for pos in memchr::memchr_iter(*first, haystack) { + // same logic + let mut matches = 1; + + for c in needle.iter().skip(1) { + if !c.eq_ignore_ascii_case(haystack.get(pos + matches)?) { + break; + } + + matches += 1; + } + + if matches == needle_len { + return Some(pos); + } + } + } + + None +} + +// main search entrypoint +// it will decide whether to call search_literal or search_pattern +pub fn search(app: &mut App, needle: &str, next: bool) -> Option { + if app.hex_view.search.mode == SearchMode::Hex { + // SearchMode::Hex will use search_pattern() if it contains patterns + let pattern_chars = ['?', '[', '(']; + + if needle.contains(|c| pattern_chars.contains(&c)) { + return search_pattern(app, needle, false); + // otherwise we use literal search, which is faster + } else if let Some(n) = hex_string_to_u8(needle) { + return search_literal(app, n, next); + } + } + // SearchMode::Utf8 + search_literal(app, needle, next) +} + +// search literal strings with memchr +pub fn search_literal>(app: &mut App, needle: T, next: bool) -> Option { + let text = needle.as_ref(); + let filesize = app.file_info.size; + let buffer = app.file_info.get_buffer(); + + if filesize == 0 || text.is_empty() { + return None; + } + + let ofs = if app.hex_view.search.direction == SearchDirection::Forward { + let start = if next { + app.hex_view.offset.checked_add(1)? + } else { + app.hex_view.offset + }; + + let contais_capital_letter = text.iter().any(|b| b.is_ascii_uppercase()); + let smart_search = contais_capital_letter && app.config.search_smartcase; + + if start < filesize { + if app.config.search_ignorecase && !smart_search { + find_nocase(buffer.get(start..)?, text).map(|pos| start + pos) + } else { + memchr::memmem::find(buffer.get(start..)?, text).map(|pos| start + pos) + } + } else { + None + } + } else { + let end = app.hex_view.offset; + + if end > 0 { + memchr::memmem::rfind(buffer.get(..end)?, text) + } else { + None + } + }; + + if ofs.is_some() { + return ofs; + } + + // ofs is None, check wrap setting + if app.config.search_wrapscan { + let ofs = if app.hex_view.search.direction == SearchDirection::Forward { + memchr::memmem::find(buffer, text) + } else { + memchr::memmem::rfind(buffer, text) + }; + + if ofs.is_some() { + return ofs; + } + } + + crate::beep!(); + None +} + +// search patterns with yara-x +pub fn search_pattern(app: &mut App, pattern: &str, nocase: bool) -> Option { if pattern.is_empty() { return None; } let string_decl = match app.hex_view.search.mode { - SearchMode::Utf8 => format!("$a = \"{pattern}\" ascii wide nocase"), + SearchMode::Utf8 => format!( + "$a = \"{}\" {}", + pattern, + if nocase { "nocase" } else { "" } + ), SearchMode::Hex => format!("$a = {{{pattern}}}"), }; @@ -87,7 +234,7 @@ pub fn search_yr(app: &mut App, pattern: &str) -> Option { return r#match.range().start.checked_add(start); } // ...so we check if wrapscan is set to try again from the beginning - } else if app.config.search_wrap { + } else if app.config.search_wrapscan { let start = 0; let slice = buffer.get(start..)?; let result = scanner.scan(slice).unwrap(); @@ -111,7 +258,7 @@ pub fn search_yr(app: &mut App, pattern: &str) -> Option { if let Some(r#match) = pattern.matches().last() { return Some(r#match.range().start); } - } else if app.config.search_wrap { + } else if app.config.search_wrapscan { let slice = buffer.get(0..)?; let result = scanner.scan(slice).unwrap(); let rule = result.matching_rules().next()?; @@ -184,43 +331,20 @@ pub fn dialog_search_events(app: &mut App, event: &Event) -> Result { } }, KeyCode::Enter => { - match app.hex_view.search.mode { - SearchMode::Utf8 => { - let text = app.hex_view.search.input_text.value().to_string(); - app.state = UIState::Normal; - - if text.is_empty() { - app.dialog_renderer = None; - return Ok(false); - } - - if let Some(ofs) = search_yr(app, &text) { - app.goto(ofs); - app.dialog_renderer = None; - } else { - app.dialog_renderer = Some(dialog_search_error_draw); - crate::beep!(); - } - } - SearchMode::Hex => { - app.state = UIState::Normal; - - let hex_string = app.hex_view.search.input_hex.value().to_string(); - - if hex_string.is_empty() { - app.dialog_renderer = None; - return Ok(false); - } - - if let Some(ofs) = search_yr(app, &hex_string) { - app.goto(ofs); - app.dialog_renderer = None; - } else { - app.dialog_renderer = Some(dialog_search_error_draw); - crate::beep!(); - } - } + let needle = match app.hex_view.search.mode { + SearchMode::Utf8 => app.hex_view.search.input_text.value().to_string(), + SearchMode::Hex => app.hex_view.search.input_hex.value().to_string(), }; + + if let Some(ofs) = search(app, &needle, false) { + app.goto(ofs); + app.dialog_renderer = None; + } else { + app.dialog_renderer = Some(dialog_search_error_draw); + crate::beep!(); + } + // TODO: draw "Searching..." + app.state = UIState::Normal; } KeyCode::Tab => { app.hex_view.search.mode.next(); @@ -257,3 +381,57 @@ pub fn dialog_search_error_draw(app: &mut App, frame: &mut Frame) { dialog.kind = MessageType::Error; dialog.render(app, frame); } + +#[cfg(test)] +mod tests { + use super::*; + use pretty_assertions::assert_eq; + + #[test] + fn test_find_nocase() { + // found + for needle in [ + b"opengl", b"OpenGL", b"OpengL", b"opengL", b"Opengl", b"OPENGL", + ] { + let r = find_nocase(b"I think OpenGL is nice", needle); + assert_eq!(r, Some(8)); + } + for needle in [b"i think", b"I think", b"i Think", b"I thinK"] { + let r = find_nocase(b"I think OpenGL is nice", needle); + assert_eq!(r, Some(0)); + } + for needle in [b"ce", b"cE", b"Ce", b"CE"] { + let r = find_nocase(b"I think OpenGL is nice", needle); + assert_eq!(r, Some(20)); + } + for needle in [b"x", b"X"] { + let r = find_nocase(b"I think OpenGL is nicX", needle); + assert_eq!(r, Some(21)); + } + + // not found + for needle in [ + b"Aopengl", b"OpeanGL", b"OpengaL", b"ope-ngL", b"Open2gl", b"OPExNGL", + ] { + let r = find_nocase(b"I think OpenGL is nice", needle); + assert_eq!(r, None); + } + for needle in [b"i t?hink", b"I thi]nk", b"i Thin/k", b"I |thinK"] { + let r = find_nocase(b"I think OpenGL is nice", needle); + assert_eq!(r, None); + } + for needle in [b"c]e", b"c,E", b"Ce0", b"CE-"] { + let r = find_nocase(b"I think OpenGL is nice", needle); + assert_eq!(r, None); + } + for needle in [b"*", b"?"] { + let r = find_nocase(b"I think OpenGL is nicX", needle); + assert_eq!(r, None); + } + + assert_eq!( + find_nocase(b"\x00\x80\xCD\x6F\x00\x00\xCE\x6F\x00\x80", b"opengl"), + None + ); + } +} From 6cd8be457d28caa9192b491aebf6d5efd68c124a Mon Sep 17 00:00:00 2001 From: merces Date: Sun, 4 Oct 2026 07:56:35 -0300 Subject: [PATCH 07/11] docs: update README --- README.md | 67 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index ee77896..8773812 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Fast Vim-inspired hex editor for the terminal - Edit in hex or ASCII - String list with regex filtering - Multiple smart ways to navigate through a file -- Find strings and hex bytes +- Find strings and hex patterns - Add comments and bookmarks - Mark blocks with colors - PE/ELF headers parsing (WIP -- not released yet) @@ -100,25 +100,29 @@ Once you load a file in **dz6**, you can use the commands below. #### Commands -| Command | Action | Parameters | Tips/Examples | -| ---------------- | ---------------------------------------------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------- | -| `` | Go to offset | | hex default; `t` suffix = decimal; `+` prefix = incremental jump; `-` prefix = decremental jump | -| `cmt` | Add `` to `` | `` `` | `cmt 1000 "my comment"` (comment at offset 0x1000; offset obeys the same rules above) | -| `sel` | Select `` bytes from `` | `` `` | `sel 40 10t` (select 10 bytes from offset 0x40) | -| `set byteline` | Set the number of bytes per line | `` or `auto` | `set byteline 8` (default is 16; `auto` enables automatic setting based on screen width) | -| `set ctrlchar` | Set the character shown in the ASCII dump for non-graphic values | `` | `set ctrlchar " "` would set a blankspace (default: `.`) | -| `set db` | Turn on database file saving/loading (default) | | A database file with a `.dz6` extension will be used to store bookmarks and comments for the file | -| `set nodb` | Turn off database file saving/loading | | | -| `set dimzero` | Dim (gray out) null bytes only (default) | | | -| `set dimctrl` | Dim all control characters | | All non-graphic characters will be dimmed | -| `set nodim` | Turn off byte dimming | | | -| `set theme` | Set the theme | `dark` or `light` | `set theme light` (default: `dark`) | -| `set view` | Changes the current view | `text`, `hex` or `header` | `set view header` (default: `hex`) | -| `set wrapscan` | Enable search results wrap | | | -| `set nowrapscan` | Disable search results wrap | | | -| `w` | Write changes to file | | | -| `wq` or `x` | Write changes to file and quit | | | -| `q` | Quit without saving changes | | In replace mode, `T` (truncate) is an exception because it modifies the file immediately. | +| Command | Action | Parameters | Tips/Examples | +| ------------------ | ---------------------------------------------------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------- | +| `` | Go to offset | | hex default; `t` suffix = decimal; `+` prefix = incremental jump; `-` prefix = decremental jump | +| `cmt` | Add `` to `` | `` `` | `cmt 1000 "my comment"` (comment at offset 0x1000; offset obeys the same rules above) | +| `sel` | Select `` bytes from `` | `` `` | `sel 40 10t` (select 10 bytes from offset 0x40) | +| `set byteline` | Set the number of bytes per line | `` or `auto` | `set byteline 8` (default is 16; `auto` enables automatic setting based on screen width) | +| `set ctrlchar` | Set the character shown in the ASCII dump for non-graphic values | `` | `set ctrlchar " "` would set a blankspace (default: `.`) | +| `set db` | Turn on database file saving/loading (default) | | A database file with a `.dz6` extension will be used to store bookmarks and comments for the file | +| `set nodb` | Turn off database file saving/loading | | | +| `set dimzero` | Dim (gray out) null bytes only (default) | | | +| `set dimctrl` | Dim all control characters | | All non-graphic characters will be dimmed | +| `set nodim` | Turn off byte dimming | | | +| `set theme` | Set the theme | `dark` or `light` | `set theme light` (default: `dark`) | +| `set view` | Changes the current view | `text`, `hex` or `header` | `set view header` (default: `hex`) | +| `set wrapscan` | Enable search results wrap | | `set ws` also works | +| `set nowrapscan` | Disable search results wrap | | `set nows` also works | +| `set ignorecase` | Enable case-insensitive search (ASCII only) | | `set ic` also works | +| `set noignorecase` | Disable case-insensitive search | | `set noic` also works | +| `set smartcase` | Enable smart case search | | if the search term contains a capital letter and `ignorecase` is enabled, disable it. `set scs` also works. | +| `set nosmartcase` | Disable smart case search | | `set noscs` also works | +| `w` | Write changes to file | | | +| `wq` or `x` | Write changes to file and quit | | | +| `q` | Quit without saving changes | | In replace mode, `T` (truncate) is an exception because it modifies the file immediately. | > If you need permanent settings, create a `$HOME/.dz6init` file containing any of the commands above, one per line. dz6 will load that at startup. Lines starting with `#` are ignored. @@ -144,9 +148,9 @@ This is the main view you would expect from a hex editor. It displays file offse | `Ctrl+x` | Decrement byte under the cursor | | | `v` | Enter [select mode](#hex-selection-mode) | | | `u` | Undo the last change made to the buffer | Use it _before_ writing to the file (`:w`) | -| `/` | Search (forward) | Search the entire file. `Tab` cycles between ASCII and hex search | +| `/` | Enter [search mode](#hex-search-mode) (forward) | Search the entire file. `Tab` cycles between UTF-8 and hex search | | `n` | Search next (forward) | | -| `?` | Search (backward) | Search the entire file. `Tab` cycles between ASCII and hex search | +| `?` | Search (backward) | Search the entire file. `Tab` cycles between UTF-8 and hex search | | `N` | Search next (backward) | | | `s` | Open [Strings](#strings) window | | | `Backspace` | Go to the previously visited offset | This is useful after a Go to command, for example | @@ -172,6 +176,25 @@ This is the main view you would expect from a hex editor. It displays file offse | `Alt+m` | Mark a block with a random color | `Alt+m` again to pick another color. `[` and `]` to navigate to block boundaries | | `Esc` | Go back to normal mode | | +#### Hex search mode + +This mode has two sub-modes: UTF-8 and HEX. The first is straightforward: search for UTF-8 strings, +but if `ignorecase` is enabled, it will only work with the ASCII character set. + +The HEX sub-mode supports [YARA-X patterns](https://virustotal.github.io/yara-x/docs/writing_rules/hex-patterns/): + +`f0f0ca` or `F0F0CA` match `f0f0ca` only (no pattern matching in this case). + +`b0 ?? ca` - `??` means "any byte", so this would match `b0b0ca`, `b0ffca`, `b042ca`... + +`b? b? ca` - a single `?` means "any nibble". This would match `b0b0ca` and `babaca` for example. + +`ba (b0|ba) ca` matches `bab0bca` or `babaca`. + +`f0 [1-3] ca` matches a sequence starting with 0xf0, followed by 1, 2, or 3 bytes of any value, then followed by 0xca. + +`b0 ~b0 ca` negation, meaning 0xb0 followed by anything but 0xb0, followed 0xca. + #### Hex replace mode | Key | Action | Tips | From a4cf53a8fda60feb60e6aef27019fd3d90cd27f4 Mon Sep 17 00:00:00 2001 From: merces Date: Sun, 4 Oct 2026 08:56:59 -0300 Subject: [PATCH 08/11] feat: case-insensitive reverse find --- src/hex/search.rs | 82 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 3 deletions(-) diff --git a/src/hex/search.rs b/src/hex/search.rs index 096f1a6..c285a44 100644 --- a/src/hex/search.rs +++ b/src/hex/search.rs @@ -107,6 +107,71 @@ fn find_nocase(haystack: &[u8], needle: &[u8]) -> Option { None } +fn rfind_nocase(haystack: &[u8], needle: &[u8]) -> Option { + // get first needle char and return early if we can't / needle.len() == 0 + let first = needle.first()?; + let needle_len = needle.len(); + + // we can't search for a needle bigger than the haystack + if needle_len > haystack.len() { + return None; + } + + if first.is_ascii_alphabetic() { + // if needle's first letter is alphabetic, we use memchr2_iter to find both variants + for pos in memchr::memrchr2_iter( + first.to_ascii_lowercase(), + first.to_ascii_uppercase(), + haystack, + ) { + let mut matches = 1; // number of matching characters + + for c in needle.iter().skip(1) { + // continue early if neddle can't fit at current pos to the end of haystack + if haystack.len() - pos + matches < needle_len { + continue; + } + + // if let Some(v) = haystack.get(pos + matches) { + if !c.eq_ignore_ascii_case(haystack.get(pos + matches)?) { + break; + } + + matches += 1; + // } + } + + if matches == needle_len { + return Some(pos); + } + } + } else { + // otherwise we call memchr_iter, which is faster + for pos in memchr::memrchr_iter(*first, haystack) { + // same logic + let mut matches = 1; + + for c in needle.iter().skip(1) { + if haystack.len() - pos + matches < needle_len { + continue; + } + + if !c.eq_ignore_ascii_case(haystack.get(pos + matches)?) { + break; + } + + matches += 1; + } + + if matches == needle_len { + return Some(pos); + } + } + } + + None +} + // main search entrypoint // it will decide whether to call search_literal or search_pattern pub fn search(app: &mut App, needle: &str, next: bool) -> Option { @@ -155,10 +220,21 @@ pub fn search_literal>(app: &mut App, needle: T, next: bool) -> O None } } else { - let end = app.hex_view.offset; + let start = if next { + app.hex_view.offset.checked_sub(1)? + } else { + app.hex_view.offset + }; + + let contais_capital_letter = text.iter().any(|b| b.is_ascii_uppercase()); + let smart_search = contais_capital_letter && app.config.search_smartcase; - if end > 0 { - memchr::memmem::rfind(buffer.get(..end)?, text) + if start < filesize && start != 0 { + if app.config.search_ignorecase && !smart_search { + rfind_nocase(buffer.get(..start)?, text) + } else { + memchr::memmem::rfind(buffer.get(..start)?, text) + } } else { None } From 219ae0fe25ae9c1c2399d8e297670cd419bf39d9 Mon Sep 17 00:00:00 2001 From: merces Date: Sun, 4 Oct 2026 23:11:04 -0300 Subject: [PATCH 09/11] feat: replace yara-x with regex --- Cargo.lock | 1118 ++------------------------------------------- Cargo.toml | 2 +- src/hex/search.rs | 160 ++++--- 3 files changed, 117 insertions(+), 1163 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5b78ef8..9f39b0e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,15 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59317f77929f0e679d39364702289274de2f0f0b22cbf50b2b8cff2169a0b27a" -dependencies = [ - "gimli 0.33.0", -] - [[package]] name = "aho-corasick" version = "1.1.5" @@ -35,17 +26,6 @@ dependencies = [ "libc", ] -[[package]] -name = "annotate-snippets" -version = "0.12.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f211a51805bc641f3ad5b7664c77d2547af685cc33b4cd8d31964027a46f13f1" -dependencies = [ - "anstyle", - "memchr", - "unicode-width", -] - [[package]] name = "anstream" version = "1.0.0" @@ -111,12 +91,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "arbitrary" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" - [[package]] name = "arboard" version = "3.6.1" @@ -134,23 +108,6 @@ dependencies = [ "x11rb", ] -[[package]] -name = "ascii_tree" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6c635b3aa665c649ad1415f1573c85957dfa47690ec27aebe7ec17efe3c643" - -[[package]] -name = "async-trait" -version = "0.1.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.6", -] - [[package]] name = "atomic" version = "0.6.1" @@ -172,32 +129,6 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "base64" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" - -[[package]] -name = "bincode" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" -dependencies = [ - "bincode_derive", - "serde", - "unty", -] - -[[package]] -name = "bincode_derive" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09" -dependencies = [ - "virtue", -] - [[package]] name = "bit-set" version = "0.5.3" @@ -224,22 +155,6 @@ name = "bitflags" version = "2.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" -dependencies = [ - "serde_core", -] - -[[package]] -name = "bitvec" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddcec3d12c579d40898fe0a9a358a803c23e9c52ca3c425707f81c9436211837" -dependencies = [ - "funty", - "radium", - "serde", - "tap", - "wyz", -] [[package]] name = "block-buffer" @@ -250,25 +165,11 @@ dependencies = [ "generic-array", ] -[[package]] -name = "bstr" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb31b46c14244e20ee9984b11bf5c992b91fb6939fea616e3512c8baecdbe5f" -dependencies = [ - "memchr", - "regex-automata", - "serde_core", -] - [[package]] name = "bumpalo" version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" -dependencies = [ - "allocator-api2", -] [[package]] name = "by_address" @@ -293,9 +194,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f360145194ee8e21db5ee7f3fcd4fe52210864c75c985dae33218202c8bbe040" +checksum = "f74872d07caf508b30a21f6836e7d7016a2eaf7d9ff4f48deaa58cd8a0407630" dependencies = [ "find-msvc-tools", "shlex", @@ -386,15 +287,6 @@ dependencies = [ "error-code", ] -[[package]] -name = "cobs" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" -dependencies = [ - "thiserror 2.0.21", -] - [[package]] name = "colorchoice" version = "1.0.5" @@ -436,21 +328,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f8f80099a98041a3d1622845c271458a2d73e688351bf3cb999266764b81d48" -[[package]] -name = "countme" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636" - -[[package]] -name = "cpp_demangle" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2bb79cb74d735044c972aae58ed0aaa9a837e85b01106a54c39e42e97f62253" -dependencies = [ - "cfg-if", -] - [[package]] name = "cpufeatures" version = "0.2.17" @@ -469,188 +346,12 @@ dependencies = [ "libc", ] -[[package]] -name = "cranelift-assembler-x64" -version = "0.132.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d521bdbc6098937af83ef4ab6d5c07398126bc71878f7ef4ea9499977978ef5" -dependencies = [ - "cranelift-assembler-x64-meta", -] - -[[package]] -name = "cranelift-assembler-x64-meta" -version = "0.132.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dde0b83164d4a497860af4236271178bc640512b067101e0853e4f74eaa4df5" -dependencies = [ - "cranelift-srcgen", -] - -[[package]] -name = "cranelift-bforest" -version = "0.132.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0111d110b72b4efad69a372e29e21628652fd0bcab66967e5c8350ab679affd5" -dependencies = [ - "cranelift-entity", - "wasmtime-internal-core", -] - -[[package]] -name = "cranelift-bitset" -version = "0.132.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf01ecc92fc5499789d79c3b817299d5a8ddd828d31dcf0f9cc3cc66f38dbb36" -dependencies = [ - "serde", - "serde_derive", - "wasmtime-internal-core", -] - -[[package]] -name = "cranelift-codegen" -version = "0.132.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cd2563bead0090c3879a7ff7327f7550c9d59bb5d05ecc8cd7886977aa3125a" -dependencies = [ - "bumpalo", - "cranelift-assembler-x64", - "cranelift-bforest", - "cranelift-bitset", - "cranelift-codegen-meta", - "cranelift-codegen-shared", - "cranelift-control", - "cranelift-entity", - "cranelift-isle", - "gimli 0.33.0", - "hashbrown 0.17.1", - "libm", - "log", - "pulley-interpreter", - "regalloc2", - "rustc-hash 2.1.3", - "serde", - "smallvec", - "target-lexicon", - "wasmtime-internal-core", -] - -[[package]] -name = "cranelift-codegen-meta" -version = "0.132.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9640d250d26f9381a73dc7f9862b27928d4809119aec73be0e556612e67b6a99" -dependencies = [ - "cranelift-assembler-x64-meta", - "cranelift-codegen-shared", - "cranelift-srcgen", - "heck", - "pulley-interpreter", -] - -[[package]] -name = "cranelift-codegen-shared" -version = "0.132.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a07f156b90efc94371ddb3536f76e4ab671ad2e093bfa5511e10198cadbb0c47" - -[[package]] -name = "cranelift-control" -version = "0.132.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a76fd9dd37dcbc3d2d2e00abe3281a7e88adc035fba3b8114cc69981576ec" -dependencies = [ - "arbitrary", -] - -[[package]] -name = "cranelift-entity" -version = "0.132.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eea22522144ba08c7e7ef94bfc25d474ef016c2771974b8ab1986734ac85965" -dependencies = [ - "cranelift-bitset", - "serde", - "serde_derive", - "wasmtime-internal-core", -] - -[[package]] -name = "cranelift-frontend" -version = "0.132.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efa2826c80dff1d93b19b3cfbcaf9fae44c78d739a98d146dd5bd89c51e14367" -dependencies = [ - "cranelift-codegen", - "log", - "smallvec", - "target-lexicon", -] - -[[package]] -name = "cranelift-isle" -version = "0.132.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e238a69b95c5415456f22189494a12db94f313bb72b6ec9cc88ddf2f1056e28e" - -[[package]] -name = "cranelift-native" -version = "0.132.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eceb0ebd8d6aef6bb287e8d532a164b0db1c0062961211e9c22a91f67521c098" -dependencies = [ - "cranelift-codegen", - "libc", - "target-lexicon", -] - -[[package]] -name = "cranelift-srcgen" -version = "0.132.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "004643f39a7bec553de5263d650db30e5b9caec1d5cbe065fd732b7ec9ae40d0" - -[[package]] -name = "crc32fast" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01a7799fd6b852db0e61728dde9a204c423b44d689dbd432522543614b490e78" -dependencies = [ - "cfg-if", -] - [[package]] name = "critical-section" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" -[[package]] -name = "crossbeam-deque" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622f3fc73690be383c7214310406f28a90e6edeadc3cea882f9d71e495b9711a" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc74980687109a3b14c72fd458107bf0baa1da1a1a805e178d15501ba9b86d9d" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6" - [[package]] name = "crossterm" version = "0.29.0" @@ -698,12 +399,6 @@ dependencies = [ "phf", ] -[[package]] -name = "daachorse" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd10668980c9e7ba8aa2e616207d9ec52f7db66ebb47db857ed1f3c342530dad" - [[package]] name = "darling" version = "0.24.1" @@ -851,7 +546,6 @@ dependencies = [ "shell-words", "toml", "tui-input", - "yara-x", ] [[package]] @@ -860,18 +554,6 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34" -[[package]] -name = "embedded-io" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" - -[[package]] -name = "embedded-io" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" - [[package]] name = "encoding_rs" version = "0.8.42" @@ -923,12 +605,6 @@ version = "13.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25929004897f2bbab309121a60400d36992f6d911d09baa6c172f6cc55706601" -[[package]] -name = "fallible-iterator" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" - [[package]] name = "fancy-regex" version = "0.11.0" @@ -980,12 +656,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - [[package]] name = "futures-core" version = "0.3.34" @@ -1037,10 +707,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", - "js-sys", "libc", "wasi", - "wasm-bindgen", ] [[package]] @@ -1067,53 +735,6 @@ dependencies = [ "rand_core 0.10.1", ] -[[package]] -name = "gimli" -version = "0.32.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" -dependencies = [ - "fallible-iterator", - "indexmap", - "stable_deref_trait", -] - -[[package]] -name = "gimli" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7f043f89559805f8c7cacc432749b2fa0d0a0a9ee46ce47164ed5ba7f126c" -dependencies = [ - "fnv", - "hashbrown 0.16.1", - "indexmap", - "stable_deref_trait", -] - -[[package]] -name = "globset" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07c34a9410465b45bd9787443bc7370f37735bad04b0f0cd57ff1a3186c98988" -dependencies = [ - "aho-corasick", - "bstr", - "log", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "globwalk" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" -dependencies = [ - "bitflags 2.13.2", - "ignore", - "walkdir", -] - [[package]] name = "goblin" version = "0.10.7" @@ -1125,12 +746,6 @@ dependencies = [ "scroll", ] -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - [[package]] name = "hashbrown" version = "0.16.1" @@ -1140,8 +755,6 @@ dependencies = [ "allocator-api2", "equivalent", "foldhash", - "serde", - "serde_core", ] [[package]] @@ -1153,8 +766,6 @@ dependencies = [ "allocator-api2", "equivalent", "foldhash", - "serde", - "serde_core", ] [[package]] @@ -1193,34 +804,12 @@ dependencies = [ "cc", ] -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - [[package]] name = "ident_case" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" -[[package]] -name = "ignore" -version = "0.4.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b69833ed729dc5aa7d19541d96d6cf8e9137194207a04916d658e43168402f" -dependencies = [ - "crossbeam-deque", - "globset", - "log", - "memchr", - "regex-automata", - "same-file", - "walkdir", - "winapi-util", -] - [[package]] name = "indexmap" version = "2.14.2" @@ -1229,8 +818,6 @@ checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" dependencies = [ "equivalent", "hashbrown 0.17.1", - "serde", - "serde_core", ] [[package]] @@ -1256,40 +843,16 @@ dependencies = [ ] [[package]] -name = "intaglio" -version = "1.15.1" +name = "is_terminal_polyfill" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eca9188c1b20836bb561bc09bb2f54e9ca99b271031b5f3ff183a00c08c98c8" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] -name = "inventory" -version = "0.3.24" +name = "itertools" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4f0c30c76f2f4ccee3fe55a2435f691ca00c0e4bd87abe4f4a851b1d4dac39b" -dependencies = [ - "rustversion", -] - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" - -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b4baf93f58d4425749ca49a51c50ebab072c5df6994d08fed93541c331481dc" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ "either", ] @@ -1330,27 +893,15 @@ checksum = "bf36173d4167ed999940f804952e6b08197cae5ad5d572eb4db150ce8ad5d58f" [[package]] name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "leb128" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c83bff1d572d6b9aeef67ddfc8448e4a3737909cb28e81f97c791b9018703e52" - -[[package]] -name = "leb128fmt" -version = "0.1.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" +checksum = "20870f649af7073d53e38067b2a84312175d56ea15217e1b15bc83506ec50afb" [[package]] name = "libc" -version = "0.2.189" +version = "0.2.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" +checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78" [[package]] name = "libm" @@ -1403,38 +954,6 @@ version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" -[[package]] -name = "logos" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb2c55a318a87600ea870ff8c2012148b44bf18b74fad48d0f835c38c7d07c5f" -dependencies = [ - "logos-derive", -] - -[[package]] -name = "logos-codegen" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58b3ffaa284e1350d017a57d04ada118c4583cf260c8fb01e0fe28a2e9cf8970" -dependencies = [ - "fnv", - "proc-macro2", - "quote", - "regex-automata", - "regex-syntax", - "syn 2.0.119", -] - -[[package]] -name = "logos-derive" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52d3a9855747c17eaf4383823f135220716ab49bea5fbea7dd42cc9a92f8aa31" -dependencies = [ - "logos-codegen", -] - [[package]] name = "lru" version = "0.18.5" @@ -1446,21 +965,12 @@ dependencies = [ [[package]] name = "mac_address" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0aeb26bf5e836cc1c341c8106051b573f1766dfa05aa87f0b98be5e51b02303" -dependencies = [ - "nix", - "winapi", -] - -[[package]] -name = "mach2" -version = "0.4.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" +checksum = "b367b50a9be9a5d3b5718c1da74e5d6b9c17647f89752ee2562a470cc3c4eb1a" dependencies = [ - "libc", + "nix 0.30.1", + "windows-sys 0.61.2", ] [[package]] @@ -1469,15 +979,6 @@ version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" -[[package]] -name = "memfd" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57804b2c9b69967f1536a56f86297e367a33b19e98852ed624b84551cdbc0d90" -dependencies = [ - "rustix", -] - [[package]] name = "memmap2" version = "0.7.1" @@ -1487,15 +988,6 @@ dependencies = [ "libc", ] -[[package]] -name = "memmap2" -version = "0.9.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0" -dependencies = [ - "libc", -] - [[package]] name = "memmem" version = "0.1.1" @@ -1519,9 +1011,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "mio" -version = "1.2.3" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b18443e9c262bfe8fa82f51666e2642c53393f7e5c27b3e1aeab922cff5b9d8" +checksum = "1788edb87fdc09c7e26304471e2f5be8cdefb1b6930d6e3985fc02ff53bf86ee" dependencies = [ "libc", "log", @@ -1539,7 +1031,7 @@ dependencies = [ "cfg-if", "libc", "log", - "memmap2 0.7.1", + "memmap2", "parking_lot", "thiserror 1.0.69", ] @@ -1555,6 +1047,18 @@ name = "nix" version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.13.2", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "nix" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ "bitflags 2.13.2", "cfg-if", @@ -1681,18 +1185,6 @@ dependencies = [ "objc2-core-foundation", ] -[[package]] -name = "object" -version = "0.39.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5a6c098c7a3b6547378093f5cc30bc54fd361ce711e05293a5cc589562739b" -dependencies = [ - "crc32fast", - "hashbrown 0.17.1", - "indexmap", - "memchr", -] - [[package]] name = "once_cell" version = "1.21.4" @@ -1888,18 +1380,6 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" -[[package]] -name = "postcard" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" -dependencies = [ - "cobs", - "embedded-io 0.4.0", - "embedded-io 0.6.1", - "serde", -] - [[package]] name = "powerfmt" version = "0.2.0" @@ -1925,49 +1405,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "protobuf" -version = "3.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d65a1d4ddae7d8b5de68153b48f6aa3bba8cb002b243dbdbc55a5afbc98f99f4" -dependencies = [ - "once_cell", - "protobuf-support", - "thiserror 1.0.69", -] - -[[package]] -name = "protobuf-support" -version = "3.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e36c2f31e0a47f9280fb347ef5e461ffcd2c52dd520d8e216b52f93b0b0d7d6" -dependencies = [ - "thiserror 1.0.69", -] - -[[package]] -name = "pulley-interpreter" -version = "45.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b04adf8f93264685f2c70a3edb8f828c791e71b22659253319c33f29d1165aef" -dependencies = [ - "cranelift-bitset", - "log", - "pulley-macros", - "wasmtime-internal-core", -] - -[[package]] -name = "pulley-macros" -version = "45.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c120a6af1a574a42efcd9df2ad27cb78bc04118c5e0c69e90599f17301a1c7a" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - [[package]] name = "quote" version = "1.0.47" @@ -1989,12 +1426,6 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - [[package]] name = "rand" version = "0.8.8" @@ -2053,7 +1484,7 @@ dependencies = [ "compact_str", "critical-section", "hashbrown 0.17.1", - "itertools 0.14.0", + "itertools", "kasuari", "lru", "palette", @@ -2118,7 +1549,7 @@ dependencies = [ "hashbrown 0.17.1", "indoc", "instability", - "itertools 0.14.0", + "itertools", "line-clipping", "ratatui-core", "serde", @@ -2148,20 +1579,6 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "regalloc2" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "757712e8e61590d6d4f5d563483755538b5aa13467837a3b41cd9832509a7f85" -dependencies = [ - "allocator-api2", - "bumpalo", - "hashbrown 0.17.1", - "log", - "rustc-hash 2.1.3", - "smallvec", -] - [[package]] name = "regex" version = "1.13.1" @@ -2191,37 +1608,6 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" -[[package]] -name = "rowan" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14b574c58582fa59fa43a2feb6608b8744184659f08a2e0117e4b8224d95ed61" -dependencies = [ - "countme", - "hashbrown 0.14.5", - "memoffset", - "rustc-hash 1.1.0", - "text-size", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b74b56ffa8bb2830709a538c2cbcae9aa062db0d2a42563bfb09bdaae44020eb" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc-hash" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" - [[package]] name = "rustc_version" version = "0.4.1" @@ -2256,15 +1642,6 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - [[package]] name = "scopeguard" version = "1.2.0" @@ -2327,20 +1704,6 @@ dependencies = [ "syn 3.0.6", ] -[[package]] -name = "serde_json" -version = "1.0.151" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" -dependencies = [ - "indexmap", - "itoa", - "memchr", - "serde", - "serde_core", - "zmij", -] - [[package]] name = "serde_spanned" version = "1.1.1" @@ -2427,15 +1790,6 @@ name = "smallvec" version = "1.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9395f0f0eee849a9b707b2f06bb92a6a422090e2123bb2ef8e87a0e61892a8e" -dependencies = [ - "serde", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "static_assertions" @@ -2503,27 +1857,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "target-lexicon" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" - -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - [[package]] name = "termina" version = "0.3.3" @@ -2565,7 +1898,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4676b37242ccbd1aabf56edb093a4827dc49086c0ffd764a5705899e0f35f8f7" dependencies = [ "anyhow", - "base64 0.22.1", + "base64", "bitflags 2.13.2", "fancy-regex", "filedescriptor", @@ -2576,7 +1909,7 @@ dependencies = [ "libc", "log", "memmem", - "nix", + "nix 0.29.0", "num-derive", "num-traits", "ordered-float", @@ -2600,12 +1933,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "text-size" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233" - [[package]] name = "thiserror" version = "1.0.69" @@ -2747,7 +2074,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16b380a1238663e5f8a691f9039c73e1cdae598a30e9855f541d29b08b53e9a5" dependencies = [ - "itertools 0.14.0", + "itertools", "unicode-segmentation", "unicode-width", ] @@ -2758,12 +2085,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" -[[package]] -name = "unty" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" - [[package]] name = "utf8parse" version = "0.2.2" @@ -2772,9 +2093,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.26.1" +version = "1.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ef6dac1e96601b4fb3acccccff2139741fcb757cb9a36089bf5be91cfb285ce" +checksum = "97277d36b9c3ace13e58fa6e753f8b0bbbf302a18dd193240d70f9e29681059a" dependencies = [ "atomic", "getrandom 0.4.3", @@ -2788,12 +2109,6 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "virtue" -version = "0.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1" - [[package]] name = "vtparse" version = "0.6.2" @@ -2803,44 +2118,6 @@ dependencies = [ "utf8parse", ] -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "walrus" -version = "0.26.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b63a2bc6e4acb4cf69080068a531bad4530791098230e972ffcb64fd1dc266" -dependencies = [ - "anyhow", - "gimli 0.32.3", - "id-arena", - "leb128", - "log", - "walrus-macro", - "wasm-encoder 0.245.1", - "wasmparser 0.245.1", -] - -[[package]] -name = "walrus-macro" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a9b0525d7ea6e5f906aca581a172e5c91b4c595290dfa8ad4a2bc9ffef33b44" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.119", -] - [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -2901,228 +2178,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "wasm-encoder" -version = "0.245.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9dca005e69bf015e45577e415b9af8c67e8ee3c0e38b5b0add5aa92581ed5c" -dependencies = [ - "leb128fmt", - "wasmparser 0.245.1", -] - -[[package]] -name = "wasm-encoder" -version = "0.248.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac92cf547bc18d27ecc521015c08c353b4f18b84ab388bb6d1b6b682c620d9b6" -dependencies = [ - "leb128fmt", - "wasmparser 0.248.0", -] - -[[package]] -name = "wasmparser" -version = "0.245.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f08c9adee0428b7bddf3890fc27e015ac4b761cc608c822667102b8bfd6995e" -dependencies = [ - "bitflags 2.13.2", - "hashbrown 0.16.1", - "indexmap", - "semver", - "serde", -] - -[[package]] -name = "wasmparser" -version = "0.248.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa4439c5eee9df71ee0c6efb37f63b1fcb1fec38f85f5142c54e7ed05d33091a" -dependencies = [ - "bitflags 2.13.2", - "hashbrown 0.17.1", - "indexmap", - "semver", - "serde", -] - -[[package]] -name = "wasmprinter" -version = "0.248.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b264a5410b008d4d199a92bf536eae703cbd614482fc1ec53831cf19e1c183" -dependencies = [ - "anyhow", - "termcolor", - "wasmparser 0.248.0", -] - -[[package]] -name = "wasmtime" -version = "45.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a83ef84ac8bab735c89e27b0268b0586099fbe81281ae45be2b8e4f407b2daa" -dependencies = [ - "addr2line", - "async-trait", - "bitflags 2.13.2", - "bumpalo", - "cc", - "cfg-if", - "libc", - "log", - "mach2", - "memfd", - "object", - "once_cell", - "postcard", - "pulley-interpreter", - "rustix", - "serde", - "serde_derive", - "smallvec", - "target-lexicon", - "wasmparser 0.248.0", - "wasmtime-environ", - "wasmtime-internal-core", - "wasmtime-internal-cranelift", - "wasmtime-internal-fiber", - "wasmtime-internal-jit-debug", - "wasmtime-internal-jit-icache-coherence", - "wasmtime-internal-unwinder", - "wasmtime-internal-versioned-export-macros", - "windows-sys 0.61.2", -] - -[[package]] -name = "wasmtime-environ" -version = "45.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439686d3deb38525c86b88bbc90f7ba669f70c8edc7d6b35147c738bbef5ff76" -dependencies = [ - "anyhow", - "cpp_demangle", - "cranelift-bforest", - "cranelift-bitset", - "cranelift-entity", - "gimli 0.33.0", - "hashbrown 0.17.1", - "indexmap", - "log", - "object", - "postcard", - "rustc-demangle", - "serde", - "serde_derive", - "sha2", - "smallvec", - "target-lexicon", - "wasm-encoder 0.248.0", - "wasmparser 0.248.0", - "wasmprinter", - "wasmtime-internal-core", -] - -[[package]] -name = "wasmtime-internal-core" -version = "45.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3073c03f97f871fe6400e68621c863b93ba79296f8e570285231952d23fcc804" -dependencies = [ - "hashbrown 0.17.1", - "libm", - "serde", -] - -[[package]] -name = "wasmtime-internal-cranelift" -version = "45.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a15981261d361f9c93b42929f446b4009840853ceea181ad6e17730f4016a0b" -dependencies = [ - "cfg-if", - "cranelift-codegen", - "cranelift-control", - "cranelift-entity", - "cranelift-frontend", - "cranelift-native", - "gimli 0.33.0", - "itertools 0.14.0", - "log", - "object", - "pulley-interpreter", - "smallvec", - "target-lexicon", - "thiserror 2.0.21", - "wasmparser 0.248.0", - "wasmtime-environ", - "wasmtime-internal-core", - "wasmtime-internal-unwinder", - "wasmtime-internal-versioned-export-macros", -] - -[[package]] -name = "wasmtime-internal-fiber" -version = "45.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33aed9d91d54c9f861ba7e3c3130bded8a7a63e01fe58c3a9a36b45d6ee0fb57" -dependencies = [ - "cc", - "cfg-if", - "libc", - "rustix", - "wasmtime-environ", - "wasmtime-internal-versioned-export-macros", - "windows-sys 0.61.2", -] - -[[package]] -name = "wasmtime-internal-jit-debug" -version = "45.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "944942118aab67e7b4febfe88a65d0af4cfd10af8ed0e79fd6cf39d75359ab7e" -dependencies = [ - "cc", - "wasmtime-internal-versioned-export-macros", -] - -[[package]] -name = "wasmtime-internal-jit-icache-coherence" -version = "45.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37dee05e8c35759826f6b926cd949c51f771b6a58619d8e60c63c3f3d3e5e59b" -dependencies = [ - "cfg-if", - "libc", - "wasmtime-internal-core", - "windows-sys 0.61.2", -] - -[[package]] -name = "wasmtime-internal-unwinder" -version = "45.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a83f7ebe911a6f1605ff0d3a678472ddb1fcc57c3e2f6bae5dd4d170b625b3ed" -dependencies = [ - "cfg-if", - "cranelift-codegen", - "log", - "object", - "wasmtime-environ", -] - -[[package]] -name = "wasmtime-internal-versioned-export-macros" -version = "45.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75980644456dc003238766254b0e5f002704630237ccd0728747991fe2739d7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - [[package]] name = "wezterm-bidi" version = "0.2.3" @@ -3211,15 +2266,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -[[package]] -name = "winapi-util" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" -dependencies = [ - "windows-sys 0.61.2", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -3380,15 +2426,6 @@ version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - [[package]] name = "x11rb" version = "0.13.2" @@ -3411,82 +2448,3 @@ name = "yansi" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" - -[[package]] -name = "yara-x" -version = "1.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "015b06cc60800856d04c3115ef6b7c6cbb95f59f20a9df4358dd2f85f3d5b391" -dependencies = [ - "annotate-snippets", - "anyhow", - "base64 0.23.1", - "bincode", - "bitflags 2.13.2", - "bitvec", - "bstr", - "daachorse", - "getrandom 0.2.17", - "globwalk", - "hex", - "indexmap", - "intaglio", - "inventory", - "itertools 0.15.0", - "js-sys", - "memchr", - "memmap2 0.9.11", - "num-derive", - "num-traits", - "protobuf", - "regex", - "regex-automata", - "regex-syntax", - "rustc-hash 2.1.3", - "serde", - "serde_json", - "smallvec", - "strum_macros", - "thiserror 2.0.21", - "walrus", - "wasm-bindgen", - "wasmtime", - "yara-x-macros", - "yara-x-parser", -] - -[[package]] -name = "yara-x-macros" -version = "1.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a120badca58e15c6cebaff85386c23b75c31f78c06ccb68d24bd7a27293563ed" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 3.0.6", -] - -[[package]] -name = "yara-x-parser" -version = "1.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20ace34cd6497968bfcb513c7bc2c3712b559e3fd1332f81ae49593da88cc5c" -dependencies = [ - "ascii_tree", - "bitflags 2.13.2", - "bstr", - "indexmap", - "itertools 0.15.0", - "logos", - "num-traits", - "rowan", - "rustc-hash 2.1.3", - "serde", -] - -[[package]] -name = "zmij" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/Cargo.toml b/Cargo.toml index 149ed66..feb73f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,6 @@ serde = { version = "1.0.228", features = ["derive"] } shell-words = "1.1.0" toml = "1.0.1" tui-input = "0.15.0" -yara-x = { version = "1.20.0", default-features = false } # The profile that 'dist' will build with [profile.dist] @@ -38,3 +37,4 @@ lto = "thin" [dev-dependencies] pretty_assertions = "1.4.1" + diff --git a/src/hex/search.rs b/src/hex/search.rs index c285a44..6f664e8 100644 --- a/src/hex/search.rs +++ b/src/hex/search.rs @@ -1,13 +1,14 @@ -use crate::widgets::{Message, MessageType}; -use crate::{app::App, editor::UIState}; +use std::io::Result; use ratatui::Frame; use ratatui::crossterm::event::{Event, KeyCode}; use ratatui::widgets::Paragraph; -use std::io::Result; +use regex::bytes::Regex; use tui_input::Input; use tui_input::backend::crossterm::EventHandler; -use yara_x; + +use crate::widgets::{Message, MessageType}; +use crate::{app::App, editor::UIState}; #[derive(Default, Debug)] pub struct Search { @@ -177,10 +178,8 @@ fn rfind_nocase(haystack: &[u8], needle: &[u8]) -> Option { pub fn search(app: &mut App, needle: &str, next: bool) -> Option { if app.hex_view.search.mode == SearchMode::Hex { // SearchMode::Hex will use search_pattern() if it contains patterns - let pattern_chars = ['?', '[', '(']; - - if needle.contains(|c| pattern_chars.contains(&c)) { - return search_pattern(app, needle, false); + if needle.contains(|c| ['?', '[', ']'].contains(&c)) { + return search_pattern(app, needle, next); // otherwise we use literal search, which is faster } else if let Some(n) = hex_string_to_u8(needle) { return search_literal(app, n, next); @@ -261,87 +260,73 @@ pub fn search_literal>(app: &mut App, needle: T, next: bool) -> O None } -// search patterns with yara-x -pub fn search_pattern(app: &mut App, pattern: &str, nocase: bool) -> Option { - if pattern.is_empty() { - return None; - } - - let string_decl = match app.hex_view.search.mode { - SearchMode::Utf8 => format!( - "$a = \"{}\" {}", - pattern, - if nocase { "nocase" } else { "" } - ), - SearchMode::Hex => format!("$a = {{{pattern}}}"), - }; +fn translate_pattern(pattern: &str) -> String { + let mut t = String::new(); + let ptn = pattern.replace(" ", ""); - let rule = format!( - r#" - rule dz6 {{ - strings: - {string_decl} - condition: - $a - }}"# - ); - - let rules = yara_x::compile(&*rule).ok()?; - let mut scanner = yara_x::Scanner::new(&rules); - let buffer = app.file_info.get_buffer(); + // 42 to \x42 + let mut next_is_first = true; - if app.hex_view.search.direction == SearchDirection::Forward { - let start = app.hex_view.offset.checked_add(1)?; - let slice = buffer.get(start..)?; + for c in ptn.chars() { + if c.is_ascii_hexdigit() { + if next_is_first { + t.push_str("\\x"); + next_is_first = false; + } else { + next_is_first = true; + } - // enable fast scan to return the first result only - scanner.fast_scan(true); + t.push(c); + } else if c == '?' { + if next_is_first { + t.push('.'); + next_is_first = false; + } else { + next_is_first = true; + } + } else if ['[', ']', '-'].contains(&c) { + t.push(c); + next_is_first = true; + } + } - let result = scanner.scan(slice).unwrap(); + t.insert_str(0, "(?s-u)"); + t +} - // if we're at the end, the rule won't match... - if let Some(rule) = result.matching_rules().next() { - // na segunda vez n tem matching rule +// search for patterns +pub fn search_pattern(app: &mut App, pattern: &str, next: bool) -> Option { + if pattern.is_empty() { + return None; + } - let pattern = rule.patterns().next()?; + if let Ok(re) = Regex::new(&translate_pattern(pattern)) { + let buffer = app.file_info.get_buffer(); - if let Some(r#match) = pattern.matches().next() { - // the search result is an offset from start, so we add start to it - return r#match.range().start.checked_add(start); + if app.hex_view.search.direction == SearchDirection::Forward { + let start = if next { + app.hex_view.offset.checked_add(1)? + } else { + app.hex_view.offset + }; + + if let Some(m) = re.find(buffer.get(start..)?) { + return Some(m.start() + start); + } else if app.config.search_wrapscan + && let Some(m) = re.find(buffer) + { + return Some(m.start() + start); } - // ...so we check if wrapscan is set to try again from the beginning - } else if app.config.search_wrapscan { - let start = 0; - let slice = buffer.get(start..)?; - let result = scanner.scan(slice).unwrap(); - let rule = result.matching_rules().next()?; - let pattern = rule.patterns().next()?; - let r#match = pattern.matches().next()?; - - return Some(r#match.range().start); - } - } else { - // backward search - // this works, but fast_scan is not set, thus the scanner will - // find all matches so we can get the last one - let slice = buffer.get(..app.hex_view.offset)?; - let result = scanner.scan(slice).unwrap(); - - if let Some(rule) = result.matching_rules().next() { - let pattern = rule.patterns().next()?; - - // get the last match - if let Some(r#match) = pattern.matches().last() { - return Some(r#match.range().start); + } else { + let start = app.hex_view.offset; + + if let Some(m) = re.find_iter(buffer.get(..start)?).last() { + return Some(m.start()); + } else if app.config.search_wrapscan + && let Some(m) = re.find_iter(buffer).last() + { + return Some(m.start()); } - } else if app.config.search_wrapscan { - let slice = buffer.get(0..)?; - let result = scanner.scan(slice).unwrap(); - let rule = result.matching_rules().next()?; - let pattern = rule.patterns().next()?; - let r#match = pattern.matches().last()?; - - return Some(r#match.range().start); } } @@ -430,8 +415,7 @@ pub fn dialog_search_events(app: &mut App, event: &Event) -> Result { match app.hex_view.search.mode { SearchMode::Utf8 => app.hex_view.search.input_text.handle_event(event), SearchMode::Hex => { - // as per https://virustotal.github.io/yara-x/docs/writing_rules/hex-patterns/ - let allowed = [' ', '?', '[', '-', ']', 'x', 'X', '~', '(', ')', '|']; + let allowed = ['?', '[', '-', ']']; if c.is_ascii_hexdigit() || allowed.contains(&c) { app.hex_view.search.input_hex.handle_event(event) @@ -510,4 +494,16 @@ mod tests { None ); } + + #[test] + fn test_translate_pattern() { + assert_eq!( + translate_pattern("FEC01F803F??07"), + r"(?s-u)\xFE\xC0\x1F\x80\x3F.\x07" + ); + assert_eq!( + translate_pattern("FEC01F803F[00-ff]07"), + r"(?s-u)\xFE\xC0\x1F\x80\x3F[\x00-\xff]\x07" + ); + } } From 6811de5ca0b084ead89be0dac850f0c36a35318d Mon Sep 17 00:00:00 2001 From: merces Date: Wed, 7 Oct 2026 23:51:43 -0300 Subject: [PATCH 10/11] refactor: drop jumps support in hex patterns --- CHANGELOG.md | 2 ++ README.md | 14 +++----- src/hex/search.rs | 87 ++++++++++++++++++++++++++++++----------------- 3 files changed, 61 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46b6306..9591f9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ - Header view: new view to inspect ELF and PE executables. - Added a command to change the view (same as pressing `Tab`). Example: `:set view hex` (possible values are `text`, `hex`, and `header`). It can be used in `~/.dz6init` to set the default view when dz6 is loaded. - Added support for comments / lines starting with `#` in `~/.dz6init`. +- Add basic hex pattern search. +- Spache characters in hex patterns are ignored. ## Breaking changes: - `Tab` cycles through available views now (`Enter` no longer does that). diff --git a/README.md b/README.md index 8773812..aad1379 100644 --- a/README.md +++ b/README.md @@ -181,19 +181,13 @@ This is the main view you would expect from a hex editor. It displays file offse This mode has two sub-modes: UTF-8 and HEX. The first is straightforward: search for UTF-8 strings, but if `ignorecase` is enabled, it will only work with the ASCII character set. -The HEX sub-mode supports [YARA-X patterns](https://virustotal.github.io/yara-x/docs/writing_rules/hex-patterns/): +The HEX sub-mode is used to search for byte sequences. Examples: -`f0f0ca` or `F0F0CA` match `f0f0ca` only (no pattern matching in this case). +`f0f0ca` (or `F0F0CA`) matches the sequence `f0f0ca` . -`b0 ?? ca` - `??` means "any byte", so this would match `b0b0ca`, `b0ffca`, `b042ca`... - -`b? b? ca` - a single `?` means "any nibble". This would match `b0b0ca` and `babaca` for example. - -`ba (b0|ba) ca` matches `bab0bca` or `babaca`. +It also has support for basic pattern matching: -`f0 [1-3] ca` matches a sequence starting with 0xf0, followed by 1, 2, or 3 bytes of any value, then followed by 0xca. - -`b0 ~b0 ca` negation, meaning 0xb0 followed by anything but 0xb0, followed 0xca. +`b0 ?? ca` - `??` means "any byte", so this would match `b0b0ca`, `b0ffca`, `b042ca`... #### Hex replace mode diff --git a/src/hex/search.rs b/src/hex/search.rs index 6f664e8..e0d178f 100644 --- a/src/hex/search.rs +++ b/src/hex/search.rs @@ -45,10 +45,12 @@ pub enum SearchDirection { } fn hex_string_to_u8(hex_string: &str) -> Option> { - if hex_string.is_empty() || !hex_string.len().is_multiple_of(2) { + let s = hex_string.replace(" ", ""); + + if s.is_empty() || !s.len().is_multiple_of(2) { return None; } - let bytes = hex::decode(hex_string).unwrap(); + let bytes = hex::decode(s).unwrap(); Some(bytes) } @@ -183,6 +185,8 @@ pub fn search(app: &mut App, needle: &str, next: bool) -> Option { // otherwise we use literal search, which is faster } else if let Some(n) = hex_string_to_u8(needle) { return search_literal(app, n, next); + } else { + return None; } } // SearchMode::Utf8 @@ -260,10 +264,21 @@ pub fn search_literal>(app: &mut App, needle: T, next: bool) -> O None } -fn translate_pattern(pattern: &str) -> String { +fn translate_pattern(pattern: &str) -> Option { let mut t = String::new(); let ptn = pattern.replace(" ", ""); + // because we don't support nibble-level matching yet, + // # of question marks + # of hex digits should be even + if !ptn + .chars() + .filter(|c| c.is_ascii_hexdigit() || *c == '?') + .count() + .is_multiple_of(2) + { + return None; + } + // 42 to \x42 let mut next_is_first = true; @@ -291,7 +306,7 @@ fn translate_pattern(pattern: &str) -> String { } t.insert_str(0, "(?s-u)"); - t + Some(t) } // search for patterns @@ -300,32 +315,34 @@ pub fn search_pattern(app: &mut App, pattern: &str, next: bool) -> Option return None; } - if let Ok(re) = Regex::new(&translate_pattern(pattern)) { - let buffer = app.file_info.get_buffer(); + if let Some(ptn) = &translate_pattern(pattern) { + if let Ok(re) = Regex::new(ptn) { + let buffer = app.file_info.get_buffer(); + + if app.hex_view.search.direction == SearchDirection::Forward { + let start = if next { + app.hex_view.offset.checked_add(1)? + } else { + app.hex_view.offset + }; - if app.hex_view.search.direction == SearchDirection::Forward { - let start = if next { - app.hex_view.offset.checked_add(1)? + if let Some(m) = re.find(buffer.get(start..)?) { + return Some(m.start() + start); + } else if app.config.search_wrapscan + && let Some(m) = re.find(buffer) + { + return Some(m.start() + start); + } } else { - app.hex_view.offset - }; - - if let Some(m) = re.find(buffer.get(start..)?) { - return Some(m.start() + start); - } else if app.config.search_wrapscan - && let Some(m) = re.find(buffer) - { - return Some(m.start() + start); - } - } else { - let start = app.hex_view.offset; - - if let Some(m) = re.find_iter(buffer.get(..start)?).last() { - return Some(m.start()); - } else if app.config.search_wrapscan - && let Some(m) = re.find_iter(buffer).last() - { - return Some(m.start()); + let start = app.hex_view.offset; + + if let Some(m) = re.find_iter(buffer.get(..start)?).last() { + return Some(m.start()); + } else if app.config.search_wrapscan + && let Some(m) = re.find_iter(buffer).last() + { + return Some(m.start()); + } } } } @@ -397,6 +414,12 @@ pub fn dialog_search_events(app: &mut App, event: &Event) -> Result { SearchMode::Hex => app.hex_view.search.input_hex.value().to_string(), }; + if needle.is_empty() { + app.dialog_renderer = None; + app.state = UIState::Normal; + return Ok(true); + } + if let Some(ofs) = search(app, &needle, false) { app.goto(ofs); app.dialog_renderer = None; @@ -415,7 +438,7 @@ pub fn dialog_search_events(app: &mut App, event: &Event) -> Result { match app.hex_view.search.mode { SearchMode::Utf8 => app.hex_view.search.input_text.handle_event(event), SearchMode::Hex => { - let allowed = ['?', '[', '-', ']']; + let allowed = [' ', '?']; if c.is_ascii_hexdigit() || allowed.contains(&c) { app.hex_view.search.input_hex.handle_event(event) @@ -437,7 +460,7 @@ pub fn dialog_search_events(app: &mut App, event: &Event) -> Result { } pub fn dialog_search_error_draw(app: &mut App, frame: &mut Frame) { - let mut dialog = Message::from("Pattern not found"); + let mut dialog = Message::from("Not found"); dialog.kind = MessageType::Error; dialog.render(app, frame); } @@ -499,11 +522,11 @@ mod tests { fn test_translate_pattern() { assert_eq!( translate_pattern("FEC01F803F??07"), - r"(?s-u)\xFE\xC0\x1F\x80\x3F.\x07" + Some(r"(?s-u)\xFE\xC0\x1F\x80\x3F.\x07".to_string()) ); assert_eq!( translate_pattern("FEC01F803F[00-ff]07"), - r"(?s-u)\xFE\xC0\x1F\x80\x3F[\x00-\xff]\x07" + Some(r"(?s-u)\xFE\xC0\x1F\x80\x3F[\x00-\xff]\x07".to_string()) ); } } From 82f9eb875af89e0231db460a6cf1e377e2bdb192 Mon Sep 17 00:00:00 2001 From: merces Date: Thu, 8 Oct 2026 00:08:53 -0300 Subject: [PATCH 11/11] doc: update changelog --- CHANGELOG.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9591f9f..7d74831 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,12 +3,14 @@ ## dz6 v0.8.0 - Header view: new view to inspect ELF and PE executables. -- Added a command to change the view (same as pressing `Tab`). Example: `:set view hex` (possible values are `text`, `hex`, and `header`). It can be used in `~/.dz6init` to set the default view when dz6 is loaded. -- Added support for comments / lines starting with `#` in `~/.dz6init`. -- Add basic hex pattern search. -- Spache characters in hex patterns are ignored. +- Header view: added a command to change the view (same as pressing `Tab`). Example: `:set view hex` (possible values are `text`, `hex`, and `header`). It can be used in `~/.dz6init` to set the default view when dz6 starts. +- initfile: Added support for comments / lines starting with `#` in `~/.dz6init`. +- Search: add basic hex pattern search. `??` matches any byte. Space characters are ignored. +- Search: new configuration options with impact to text search: `:set ignorecase` or `:set ic` enables case-insensitive search. If smart case is also enabled with `:set smartcase` or `:set scs`, case-insensitive search is disabled when the search term contains a capital letter. +- Search: `ws` is an alias for `wrapscan`. ## Breaking changes: + - `Tab` cycles through available views now (`Enter` no longer does that). - To search over the string list, press `/` (it was `f` before).