Comparison Story: rs_textfinder_opt

5.  Conclusion — sample output, build, and references

5.  Conclusion

The four pieces come together in a small program: two library crates that know nothing about each other, a binary crate that composes them via a trait-based glue struct, and a stand-alone integration verifier that treats the compiled binary as a black box. What follows is a look at that program in action.

5.1  Sample Output

Matching files are grouped under their containing directory. The header prints the version and the resolved options; the summary line at the bottom reports how many files were visited, how many directories were entered, and how many files matched.
$ cargo run -- /P ".." /p "rs" /r "struct"

  TextFinder ver 1.2.0
 =======================
  searching path: "../"
  patterns: ["rs"]
  matching files with regex: "struct"

  ../EntryPoint/src
      "text_finder.rs"

  ../RustDirNav/src
      "dir_nav_lib.rs"

  processed 42 files in 18 dirs, 2 matched

  That's all Folks!
Directories that contain no matching files are hidden by default (/H true). Set /H false to print every directory as it is entered — useful when you want to confirm which subtrees the walker actually visits and which ones the built-in skip list rejects.
$ cargo run -- /P "." /p "rs" /r "ZZZNOMATCH" /H false

  TextFinder ver 1.2.0
 =======================
  searching path: "./"
  patterns: ["rs"]
  matching files with regex: "ZZZNOMATCH"

--./
--./RustCmdLine
--./RustCmdLine/src
--./RustDirNav
--./RustDirNav/src
--./EntryPoint
--./EntryPoint/src
--./RustTfVerify
--./RustTfVerify/src

  processed 42 files in 18 dirs, 0 matched

  That's all Folks!
Verbose mode (/v) echoes every resolved option before traversal — handy when you want to see exactly what defaults the parser applied:
$ cargo run -- /P "." /p "rs" /r "fn main" /v

  TextFinder ver 1.2.0
 =======================
  path = ./
  patterns = "rs"
  regex = "fn main"
  option: P "."
  option: p "rs"
  option: r "fn main"
  option: s "true"
  option: H "true"
  option: v "true"

  ./EntryPoint/src
      "text_finder.rs"

  processed 42 files in 18 dirs, 1 matched

  That's all Folks!

5.2  Building & Running

Each crate builds independently — there is no workspace manifest. Build the search tool from EntryPoint/; the two library crates are resolved via relative path dependencies:
# From EntryPoint/
cargo build
cargo run -- /P "." /p "rs,txt" /r "abc" /s /H   # Windows / PowerShell
cargo run -- -P "." -p "rs,txt" -r "abc" -s -H   # bash / Unix
Unit tests for each library and for the application binary:
# RustCmdLine
cd RustCmdLine
cargo test -- --show-output

# RustDirNav — must run single-threaded (test_setup must precede test_walk)
cd ../RustDirNav
cargo test -- --test-threads=1 --show-output

# EntryPoint — white-box tests for TextFinder and TfAppl
cd ../EntryPoint
cargo test -- --show-output

5.3  Integration Verification

Unit tests inside EntryPoint cover white-box state (constructor field values, setter/getter round-trips). They cannot verify the observable behavior of the compiled binary — traversal, matching output, skip lists, help-on-no-args, and so on. RustTfVerify is a separate binary crate that spawns the built text_finder executable as a subprocess and checks its stdout against each requirement assertion from Req_TextFinder.md. Results are reported as PASS, FAIL, or SKIP, and the process exits with status 1 if any assertion fails.
# Build the binary first, then run the verifier
cd EntryPoint && cargo build
cd ../RustTfVerify && cargo run

# Pass an explicit binary path if needed
cargo run -- path/to/text_finder

5.4  Design Takeaways

  • Traits factor cleanly across crate boundaries. DirEvent is two lines; those two lines let the walker live in one crate and the regex-matching application live in another without either crate importing the other's types.
  • The dominant performance win was one line. Switching from Path::is_dir() to DirEntry::file_type() avoided one stat syscall per directory entry and moved median elapsed time from ~0.91 s to ~0.61 s. Every other optimization (pre-compiled regex, raw-byte matching, buffer reuse) shaved less.
  • Ownership discipline is worth the small ergonomic cost. CmdLineParse and DirNav own all their state. No lifetime parameters bleed into caller code, and constructing one in main and passing it around requires no plumbing.
  • Verification-as-a-subprocess catches what unit tests can't. Everything observable — stdout format, skip-list behavior, help-on-no-args — is checked by RustTfVerify against the compiled binary, not against in-process mocks.

5.5  References

ResourceDescription
1. Introduction Overview, crates, CLI options, and the design roadmap for the rest of this thread.
2. RustCmdLine CmdLineParse — argv into HashMap + patterns.
3. RustDirNav Generic DirNav<App> depth-first walker.
4. EntryPoint TextFinder, TfAppl, read_file, and main.
Project Story: TextFinder Cross-language overview of the four TextFinder implementations, CLI, performance, and the optimization summary.
Rust regex crate DFA-based regex engine; regex::bytes::Regex is used here to match against raw &[u8].
RsTextFinder repository Source of all four crates discussed in this thread.