grep_searcher/lib.rs
1/*!
2This crate provides an implementation of line oriented search, with optional
3support for multi-line search.
4
5# Brief overview
6
7The principle type in this crate is a [`Searcher`], which can be configured
8and built by a [`SearcherBuilder`]. A `Searcher` is responsible for reading
9bytes from a source (e.g., a file), executing a search of those bytes using
10a `Matcher` (e.g., a regex) and then reporting the results of that search to
11a [`Sink`] (e.g., stdout). The `Searcher` itself is principally responsible
12for managing the consumption of bytes from a source and applying a `Matcher`
13over those bytes in an efficient way. The `Searcher` is also responsible for
14inverting a search, counting lines, reporting contextual lines, detecting
15binary data and even deciding whether or not to use memory maps.
16
17A `Matcher` (which is defined in the
18[`grep-matcher`](https://crates.io/crates/grep-matcher) crate) is a trait
19for describing the lowest levels of pattern search in a generic way. The
20interface itself is very similar to the interface of a regular expression.
21For example, the [`grep-regex`](https://crates.io/crates/grep-regex)
22crate provides an implementation of the `Matcher` trait using Rust's
23[`regex`](https://crates.io/crates/regex) crate.
24
25Finally, a `Sink` describes how callers receive search results producer by a
26`Searcher`. This includes routines that are called at the beginning and end of
27a search, in addition to routines that are called when matching or contextual
28lines are found by the `Searcher`. Implementations of `Sink` can be trivially
29simple, or extraordinarily complex, such as the `Standard` printer found in
30the [`grep-printer`](https://crates.io/crates/grep-printer) crate, which
31effectively implements grep-like output. This crate also provides convenience
32`Sink` implementations in the [`sinks`] sub-module for easy searching with
33closures.
34
35# Example
36
37This example shows how to execute the searcher and read the search results
38using the [`UTF8`](sinks::UTF8) implementation of `Sink`.
39
40```
41use {
42 grep_matcher::Matcher,
43 grep_regex::RegexMatcher,
44 grep_searcher::Searcher,
45 grep_searcher::sinks::UTF8,
46};
47
48const SHERLOCK: &'static [u8] = b"\
49For the Doctor Watsons of this world, as opposed to the Sherlock
50Holmeses, success in the province of detective work must always
51be, to a very large extent, the result of luck. Sherlock Holmes
52can extract a clew from a wisp of straw or a flake of cigar ash;
53but Doctor Watson has to have it taken out for him and dusted,
54and exhibited clearly, with a label attached.
55";
56
57let matcher = RegexMatcher::new(r"Doctor \w+")?;
58let mut matches: Vec<(u64, String)> = vec![];
59Searcher::new().search_slice(&matcher, SHERLOCK, UTF8(|lnum, line| {
60 // We are guaranteed to find a match, so the unwrap is OK.
61 let mymatch = matcher.find(line.as_bytes())?.unwrap();
62 matches.push((lnum, line[mymatch].to_string()));
63 Ok(true)
64}))?;
65
66assert_eq!(matches.len(), 2);
67assert_eq!(
68 matches[0],
69 (1, "Doctor Watsons".to_string())
70);
71assert_eq!(
72 matches[1],
73 (5, "Doctor Watson".to_string())
74);
75
76# Ok::<(), Box<dyn std::error::Error>>(())
77```
78
79See also `examples/search-stdin.rs` from the root of this crate's directory
80to see a similar example that accepts a pattern on the command line and
81searches stdin.
82*/
83
84#![deny(missing_docs)]
85
86pub use crate::{
87 lines::{LineIter, LineStep},
88 searcher::{
89 BinaryDetection, ConfigError, Encoding, MmapChoice, Searcher,
90 SearcherBuilder,
91 },
92 sink::{
93 Sink, SinkContext, SinkContextKind, SinkError, SinkFinish, SinkMatch,
94 sinks,
95 },
96};
97
98#[macro_use]
99mod macros;
100
101mod line_buffer;
102mod lines;
103mod searcher;
104mod sink;
105#[cfg(test)]
106mod testutil;