monster_regex/captures/
mod.rs

1/// Represents a single match within the text, defined by a start and end byte offset.
2#[derive(Debug, Clone, PartialEq, Eq)]
3pub struct Match {
4    /// The byte index where the match starts (inclusive).
5    pub start: usize,
6    /// The byte index where the match ends (exclusive).
7    pub end: usize,
8}
9
10impl Match {
11    /// Returns the length of the match in bytes.
12    pub fn len(&self) -> usize {
13        self.end - self.start
14    }
15
16    /// Returns true if the match has a length of 0.
17    pub fn is_empty(&self) -> bool {
18        self.start == self.end
19    }
20
21    /// Returns the substring of the original text corresponding to this match.
22    ///
23    /// # Panics
24    ///
25    /// Panics if the indices are out of bounds of the provided text or do not lie on UTF-8 boundaries.
26    pub fn as_str<'a>(&self, text: &'a str) -> &'a str {
27        &text[self.start..self.end]
28    }
29}
30
31/// Represents the results of a regex match, including the full match and any captured groups.
32#[derive(Debug, Clone)]
33pub struct Captures {
34    /// The match corresponding to the entire regex pattern (group 0).
35    pub full_match: Match,
36    /// Ordered list of captured groups (group 1, group 2, etc.).
37    /// `None` indicates the group exists in the pattern but did not participate in the match.
38    pub groups: Vec<Option<Match>>,
39    /// Map of named capture groups to their matches.
40    pub named: std::collections::HashMap<String, Match>,
41}
42
43impl Captures {
44    /// Returns the match associated with the capture group at `index`.
45    ///
46    /// * `0` corresponds to the entire match.
47    /// * `1..` corresponds to the parenthesized capture groups.
48    ///
49    /// Returns `None` if the index is out of bounds or if the group did not participate in the match.
50    pub fn get(&self, index: usize) -> Option<&Match> {
51        if index == 0 {
52            Some(&self.full_match)
53        } else {
54            self.groups.get(index - 1).and_then(|g| g.as_ref())
55        }
56    }
57
58    /// Returns the match associated with a named capture group.
59    pub fn get_named(&self, name: &str) -> Option<&Match> {
60        self.named.get(name)
61    }
62
63    /// Returns the substring of the original text for the capture group at `index`.
64    pub fn as_str<'a>(&self, text: &'a str, index: usize) -> Option<&'a str> {
65        self.get(index).map(|m| m.as_str(text))
66    }
67
68    /// Returns the substring of the original text for a named capture group.
69    pub fn as_str_named<'a>(&self, text: &'a str, name: &str) -> Option<&'a str> {
70        self.get_named(name).map(|m| m.as_str(text))
71    }
72}