1use crate::errors::ParseResult;
2use crate::peek::{PeekResult, Peekable, Peeking};
3use crate::scanner::Scanner;
4
5pub struct Peeker<'a, 'b, T, S, E> {
7 scanner: &'b Scanner<'a, T>,
8 peekables: Vec<Box<dyn Peekable<'a, T, S, E> + 'a>>,
10}
11
12impl<'a, 'b, T, S, E> Peeker<'a, 'b, T, S, E> {
13 pub fn new(scanner: &'b Scanner<'a, T>) -> Self {
14 Self {
15 scanner,
16 peekables: vec![],
17 }
18 }
19}
20
21impl<'a, 'b, T, S, E> Peeker<'a, 'b, T, S, E> {
22 pub fn add_peekable<F: Peekable<'a, T, S, E> + 'a>(mut self, peekable: F) -> Self {
24 self.peekables.push(Box::new(peekable));
25 self
26 }
27
28 pub fn peek(self) -> ParseResult<Option<Peeking<'b, T, S, E>>> {
30 let mut result = None;
31 for peekable in self.peekables.into_iter() {
33 let peek_result = peekable.peek(self.scanner)?;
34 match peek_result {
36 PeekResult::Found {
38 start,
39 end,
40 end_slice,
41 } => {
42 let remaining = self.scanner.remaining();
44 let data = &remaining[..end_slice];
45 let new_forecast = Peeking {
46 start,
47 end,
48 data,
49 end_slice,
50 };
51 match &result {
52 None => {
54 result = Some(new_forecast);
56 }
57 Some(min_forecast) => {
59 if new_forecast.data.len() < min_forecast.data.len() {
62 result = Some(new_forecast);
64 }
65 }
66 }
67 }
68 PeekResult::NotFound => {}
70 }
71 }
72 Ok(result)
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use crate::bytes::token::Token;
79 use crate::peek::{Until, UntilEnd};
80 use crate::peeker::Peeker;
81 use crate::scanner::Scanner;
82
83 #[test]
84 fn test_peeker() {
85 let data = b"data\n";
86 let mut scanner = Scanner::new(data);
87 let peeker = Peeker::new(&mut scanner)
88 .add_peekable(Until::new(Token::Ln))
89 .add_peekable(UntilEnd::default());
90 let result = peeker
91 .peek()
92 .expect("failed to parse")
93 .expect("failed to peek");
94 assert_eq!(result.data, "data".as_bytes());
95
96 let data = b"data";
97 let mut scanner = Scanner::new(data);
98 let peeker = Peeker::new(&mut scanner)
99 .add_peekable(Until::new(Token::Ln))
100 .add_peekable(UntilEnd::default());
101 let result = peeker
102 .peek()
103 .expect("failed to parse")
104 .expect("failed to peek");
105 assert_eq!(result.data, "data".as_bytes());
106 }
107}