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}