aoc_parse/parsers/
exact.rs1use crate::{ParseContext, ParseIter, Parser, Reported, Result};
4
5pub struct ExactParseIter {
6 end: usize,
7}
8
9impl Parser for str {
10 type Output = ();
11 type RawOutput = ();
12 type Iter<'parse> = ExactParseIter;
13
14 fn parse_iter<'parse>(
15 &'parse self,
16 context: &mut ParseContext<'parse>,
17 start: usize,
18 ) -> Result<ExactParseIter, Reported> {
19 if context.source()[start..].starts_with(self) {
20 Ok(ExactParseIter {
21 end: start + self.len(),
22 })
23 } else {
24 Err(context.error_expected(start, &format!("{self:?}")))
25 }
26 }
27}
28
29impl Parser for char {
30 type Output = ();
31 type RawOutput = ();
32 type Iter<'parse> = ExactParseIter;
33
34 fn parse_iter<'parse>(
35 &'parse self,
36 context: &mut ParseContext<'parse>,
37 start: usize,
38 ) -> Result<ExactParseIter, Reported> {
39 if context.source()[start..].starts_with(*self) {
40 Ok(ExactParseIter {
41 end: start + self.len_utf8(),
42 })
43 } else {
44 Err(context.error_expected(start, &format!("{self:?}")))
45 }
46 }
47}
48
49impl<'parse> ParseIter<'parse> for ExactParseIter {
50 type RawOutput = ();
51 fn match_end(&self) -> usize {
52 self.end
53 }
54 fn backtrack(&mut self, _context: &mut ParseContext<'parse>) -> Result<(), Reported> {
55 Err(Reported)
56 }
57 fn convert(&self) {}
58}
59
60#[cfg(test)]
61mod tests {
62 use crate::testing::*;
63
64 #[test]
65 fn test_string_lifetime() {
66 let x = format!("{} {}!", "hello", "world");
70 let p: &str = &x;
71 assert_parse_eq(&p, "hello world!", ());
72 }
73
74 #[test]
75 fn test_exact_char_errors() {
76 let p = '\n';
77 assert_parse_error(&p, "q", r#"expected '\n' at"#);
78 assert_parse_error(&p, "", r#"expected '\n' at end"#);
79 }
80}