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
| Resource | Description |
|
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. |