Skip to main content

Finder

Trait Finder 

Source
pub trait Finder: Send + Sync {
Show 19 methods // Required methods fn id(&self) -> &'static str; fn find(&self, s: &str) -> Option<Range<usize>>; // Provided methods fn dispatchable(&self) -> bool { ... } fn could_start_at(&self, _byte: u8) -> bool { ... } fn try_at(&self, _input: &[u8], _pos: usize) -> Option<Range<usize>> { ... } fn could_start_after(&self, _prev: u8, _cur: u8) -> bool { ... } fn could_continue_with(&self, _cur: u8, _next: u8) -> bool { ... } fn try_at_memo( &self, input: &[u8], pos: usize, memo: &mut Memo, ) -> Option<Range<usize>> { ... } fn try_trigger_at_memo( &self, input: &[u8], pos: usize, memo: &mut Memo, ) -> Option<Range<usize>> { ... } fn line_agnostic(&self) -> bool { ... } fn anchor(&self) -> Option<Anchor> { ... } fn prefixes(&self) -> Vec<Vec<u8>> { ... } fn run_rules(&self) -> Vec<RunRule> { ... } fn triggerable(&self) -> bool { ... } fn could_trigger_at(&self, _byte: u8) -> bool { ... } fn has_trigger_context(&self) -> bool { ... } fn trigger_context(&self, _prev2: u8, _prev1: u8) -> bool { ... } fn trigger_context_exempt(&self, _next: Option<u8>) -> bool { ... } fn try_trigger_at(&self, _input: &[u8], _pos: usize) -> Option<Range<usize>> { ... }
}
Expand description

A trait for finding patterns in text.

All finders implement this trait. A finder implementation should be stateless; it’s up to the caller to call it repeatedly until no more results can be extracted.

§Contract

  • Returned ranges are non-empty (start < end) and lie on UTF-8 character boundaries.
  • try_at/try_trigger_at receive positions into the whole line and return absolute ranges.
  • Matches produced through the scanner::Scanner are disjoint per finder and position-sorted.

Note that iterating with find over advancing sub-slices (as below) erases the left context at each slice boundary, so finders that reject matches based on what precedes them (e.g. a handle glued to a word) can accept a match at position 0 of a sub-slice that the scanner::Scanner — which always sees the whole line — would reject. The Scanner behavior is authoritative; prefer it over hand-rolled find loops.

§Example

use squeeze::{uri::URI, Finder};

let finder = URI::default();
let text = "Check https://foo.com and https://bar.com";

let mut results = Vec::new();
let mut idx = 0;

while idx < text.len() {
    if let Some(range) = finder.find(&text[idx..]) {
        results.push(&text[idx + range.start..idx + range.end]);
        idx += range.end;
    } else {
        break;
    }
}

assert_eq!(results, vec!["https://foo.com", "https://bar.com"]);

Required Methods§

Source

fn id(&self) -> &'static str

Returns a unique identifier for this finder.

Source

fn find(&self, s: &str) -> Option<Range<usize>>

Finds the first match in the given string.

Returns Some(range) containing the byte range of the match, or None if no match is found. The range is relative to the input string slice.

Provided Methods§

Source

fn dispatchable(&self) -> bool

Whether this finder supports dispatch-mode scanning via try_at.

Source

fn could_start_at(&self, _byte: u8) -> bool

Whether the given byte could be the first byte of a match. Only meaningful when dispatchable returns true.

Source

fn try_at(&self, _input: &[u8], _pos: usize) -> Option<Range<usize>>

Try to find a match starting exactly at pos in the full input. Only called when dispatchable returns true.

Source

fn could_start_after(&self, _prev: u8, _cur: u8) -> bool

Whether a match could be attempted at byte cur when the byte immediately before it is prev: a dispatch-mode start, or a trigger-mode trigger byte.

Only meaningful when dispatchable or triggerable returns true. Must agree with try_at (or try_trigger_at): whenever this returns false, the attempt must return None in that context. The scanner::Scanner folds the answers into lookup tables so positions that cannot start a match never reach the finder.

Source

fn could_continue_with(&self, _cur: u8, _next: u8) -> bool

Whether an attempt at byte cur could succeed when the byte immediately after it is next. Same contract as could_start_after.

Source

fn try_at_memo( &self, input: &[u8], pos: usize, memo: &mut Memo, ) -> Option<Range<usize>>

try_at with a per-line Memo; the scanner calls this variant. Finders whose attempts can rescan the same bytes override it to remember what already failed. Must return exactly what try_at returns.

Source

fn try_trigger_at_memo( &self, input: &[u8], pos: usize, memo: &mut Memo, ) -> Option<Range<usize>>

try_trigger_at with a per-line Memo, same contract as try_at_memo.

Source

fn line_agnostic(&self) -> bool

Whether try_at/try_trigger_at give the same answer on a whole buffer as on the line alone: \n and \r never belong to a match, and every walk treats them exactly like the end of the input (as a boundary), so a match never depends on what surrounds its line. A finder that matches “up to the end of the line” (codetag), accepts line terminators as whitespace (JSON, phone) or otherwise looks at the line as a whole must keep the default. Line-agnostic finders are run over whole buffers with absolute positions, which lets the scanner skip resolving the line of every candidate; property tests compare both modes. Defaults to false.

Source

fn anchor(&self) -> Option<Anchor>

Bytes every match of this dispatch finder contains (bytes), and the bytes that can separate a match start from the first of them (walk). When every finder of a scanner declares an anchor (or is a trigger finder) and the anchor bytes number three or fewer, the scanner searches for those bytes with memchr, walks back over walk and tries the dispatch positions in order, so lines without an anchor byte cost nothing.

Contract: for every range try_at returns, some byte of the range is in bytes, and every byte from the range start up to the first such byte is in walk.

Source

fn prefixes(&self) -> Vec<Vec<u8>>

Byte strings, ASCII case ignored, one of which starts the input at every position where try_at can match (todo for --todo codetags). A finder that would otherwise need the block classifier is then found by searching for them. Empty when unknown.

Contract: try_at(input, pos) returns None unless input[pos..] starts with one of the prefixes, ASCII case ignored.

Source

fn run_rules(&self) -> Vec<RunRule>

Rules on the digit or hex run starting at a candidate position, evaluated with RunRule::allow before try_at is called. Same contract as could_start_after: when the rules reject a position, try_at must return None there. The scanner measures the runs once per position for all finders.

Source

fn triggerable(&self) -> bool

Whether this finder supports trigger-mode scanning.

Trigger-mode is for finders whose cheapest reliable signal is inside the match rather than at the first byte, such as the @ in an email address or : in a URI.

Source

fn could_trigger_at(&self, _byte: u8) -> bool

Whether the given byte could trigger a match for this finder. Only meaningful when triggerable returns true.

Source

fn has_trigger_context(&self) -> bool

Whether the trigger context gate constrains anything: the scanner then tabulates trigger_context over the 65536 pairs of previous bytes and trigger_context_exempt over the next bytes, once, and consults them before calling the finder. Defaults to false.

Source

fn trigger_context(&self, _prev2: u8, _prev1: u8) -> bool

Whether a match may be triggered at a byte preceded by prev2 and prev1, unless the byte after the trigger is exempt (trigger_context_exempt): a necessary condition for try_trigger_at to match at that position. The scanner passes a space for a missing previous byte (the trigger sits in the first two bytes of the input). Defaults to true.

Source

fn trigger_context_exempt(&self, _next: Option<u8>) -> bool

Whether a trigger followed by next (None at the end of the input) escapes the previous-bytes condition: the URI finder needs a registered scheme before a colon unless // follows. Defaults to false.

Source

fn try_trigger_at(&self, _input: &[u8], _pos: usize) -> Option<Range<usize>>

Try to find a match triggered by pos in the full input. Only called when triggerable returns true.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§