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}