flexi_parse/
lookahead.rs

1use crate::error::Error;
2use crate::private::Marker;
3use crate::private::Sealed;
4use crate::token::Token;
5use crate::ParseBuffer;
6
7use std::collections::HashSet;
8use std::sync::Mutex;
9
10/// A type for peeking at the next token, and generating a helpful error if it
11/// isn't an expected type.
12pub struct Lookahead<'a> {
13    stream: ParseBuffer<'a>,
14    comparisons: Mutex<HashSet<String>>,
15}
16
17impl<'a> Lookahead<'a> {
18    pub(crate) fn new(stream: ParseBuffer<'a>) -> Lookahead<'a> {
19        Lookahead {
20            stream,
21            comparisons: Mutex::new(HashSet::new()),
22        }
23    }
24
25    /// Returns true if the next token is the given type.
26    ///
27    /// ## Panics
28    /// Panics if another thread panicked while peeking through this value.
29    pub fn peek<T: Peek>(&self, token: T) -> bool {
30        if self.stream.peek(token) {
31            true
32        } else {
33            self.comparisons.lock().unwrap().insert(T::Token::display());
34            false
35        }
36    }
37
38    /// Generates an error based on the peek attempts.
39    ///
40    /// ## Panics
41    /// Panics if another thread panicked while peeking through this value.
42    pub fn error(self) -> Error {
43        self.stream
44            .unexpected_token(self.comparisons.into_inner().unwrap())
45    }
46}
47
48/// Types that can be parsed by looking at a single token.
49///
50/// This trait is sealed, and cannot be implemented for types outside of this
51/// crate.
52pub trait Peek: Sealed {
53    #[doc(hidden)]
54    type Token: Token;
55}
56
57impl<F: FnOnce(Marker) -> T, T: Token> Sealed for F {}
58
59impl<F: FnOnce(Marker) -> T, T: Token> Peek for F {
60    type Token = T;
61}