Skip to main content

peeking/
peeking.rs

1use elyze::errors::ParseResult;
2use elyze::matcher::Match;
3use elyze::peek::{PeekResult, Peekable};
4use elyze::recognizer::Recognizable;
5use elyze::scanner::Scanner;
6
7struct CloseParentheses;
8
9impl Match<u8> for CloseParentheses {
10    fn is_matching(&self, data: &[u8]) -> (bool, usize) {
11        if data[0] == b')' {
12            (true, 1)
13        } else {
14            (false, 0)
15        }
16    }
17
18    fn size(&self) -> usize {
19        1
20    }
21}
22
23struct ParenthesesGroup;
24
25impl<'a> Peekable<'a, u8> for ParenthesesGroup {
26    fn peek(&self, scanner: &Scanner<'a, u8>) -> ParseResult<PeekResult> {
27        // create an internal scanner allowing to peek data without alterating the original scanner
28        let mut inner_scanner = Scanner::new(&scanner.remaining());
29
30        // loop on each byte until we find a close parenthesis
31        loop {
32            if inner_scanner.is_empty() {
33                // we have reached the end without finding a close parenthesis
34                break;
35            }
36            if CloseParentheses.recognize(&mut inner_scanner)?.is_some() {
37                // we have found a close parenthesis
38                return Ok(PeekResult::Found {
39                    // we return the position of the close parenthesis
40                    end_slice: inner_scanner.current_position(),
41                    // our peeking doesn't include a start element
42                    start_element_size: 0,
43                    // the size of the end element is a close parenthesis of 1 byte
44                    end_element_size: 1,
45                });
46            }
47
48            // consume the current byte
49            inner_scanner.bump_by(1);
50        }
51
52        // At this point, we have reached the end of available data without finding a close parenthesis
53        Ok(PeekResult::NotFound)
54    }
55}
56
57fn main() -> ParseResult<()> {
58    let data = b"7 * ( 1 + 2 )";
59    let mut scanner = Scanner::new(data);
60    scanner.bump_by(5); // consumes : 7 * (
61    let result = ParenthesesGroup.peek(&scanner)?;
62    if let PeekResult::Found {
63        end_slice,
64        end_element_size,
65        ..
66    } = result
67    {
68        println!(
69            "{:?}",
70            // to found the real size of enclosed data, we need to subtract the size of the end element
71            String::from_utf8_lossy(&scanner.remaining()[..end_slice - end_element_size]) // 1 + 2
72        );
73    } else {
74        println!("not found");
75    }
76    println!(
77        "scanner: {:?}",
78        // the scanner itself remains unchanged
79        String::from_utf8_lossy(scanner.remaining()) // scanner: " 1 + 2 )"
80    );
81    Ok(())
82}