dcbor_pattern/parse/
mod.rs

1pub mod meta;
2mod structure;
3mod token;
4pub mod value;
5
6// pub use meta::*;
7// pub use structure::*;
8pub use token::*;
9
10// pub use value::*;
11use crate::{Error, Pattern, Result};
12
13impl Pattern {
14    /// Parse a pattern expression from a string.
15    pub fn parse(input: &str) -> Result<Self> {
16        let (pattern, consumed) = Self::parse_partial(input)?;
17        if consumed < input.len() {
18            // Find where we stopped to provide accurate error span
19            return Err(Error::ExtraData(consumed..input.len()));
20        }
21        Ok(pattern)
22    }
23
24    /// Parses a pattern from the beginning of a string and returns both
25    /// the parsed Pattern and the number of bytes consumed.
26    ///
27    /// Unlike `parse()`, this function succeeds even if additional
28    /// characters follow the first pattern. The returned index points to the
29    /// first unparsed character after the pattern.
30    ///
31    /// # Example
32    ///
33    /// ```rust
34    /// # use dcbor_pattern::Pattern;
35    /// let (pattern, consumed) = Pattern::parse_partial("true rest").unwrap();
36    /// assert_eq!(pattern, Pattern::bool(true));
37    /// assert_eq!(consumed, 5); // "true ".len() - includes whitespace
38    /// ```
39    pub fn parse_partial(input: &str) -> Result<(Self, usize)> {
40        use logos::Logos;
41
42        use crate::parse::{Token, meta::parse_or};
43
44        let mut lexer = Token::lexer(input);
45        let pattern = parse_or(&mut lexer)?;
46
47        // Calculate consumed bytes - much simpler than current approach!
48        let consumed = match lexer.next() {
49            Some(_) => lexer.span().start,
50            None => input.len(),
51        };
52
53        Ok((pattern, consumed))
54    }
55}