Skip to main content

wowlab_parsers/parsers/
token_stream.rs

1/// Cursor over a slice of tokens with peek/advance semantics.
2#[derive(Debug)]
3pub struct TokenStream<'a, T> {
4    tokens: &'a [T],
5    pos: usize,
6}
7
8impl<'a, T> TokenStream<'a, T> {
9    pub fn new(tokens: &'a [T]) -> Self {
10        Self { tokens, pos: 0 }
11    }
12
13    #[inline]
14    #[must_use]
15    pub fn peek(&self) -> Option<&'a T> {
16        self.tokens.get(self.pos)
17    }
18
19    #[inline]
20    pub fn advance(&mut self) -> Option<&'a T> {
21        let token = self.tokens.get(self.pos)?;
22
23        self.pos += 1;
24
25        Some(token)
26    }
27
28    #[inline]
29    #[must_use]
30    pub fn pos(&self) -> usize {
31        self.pos
32    }
33
34    #[inline]
35    #[must_use]
36    pub fn is_empty(&self) -> bool {
37        self.pos >= self.tokens.len()
38    }
39
40    #[inline]
41    #[must_use]
42    pub fn remaining(&self) -> &'a [T] {
43        // BOUNDS: self.pos is always <= self.tokens.len(); advance only increments after a bounds-checked get.
44        &self.tokens[self.pos..]
45    }
46
47    #[inline]
48    #[must_use]
49    pub fn len(&self) -> usize {
50        self.tokens.len()
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use googletest::prelude::*;
57
58    use super::*;
59
60    #[gtest]
61    fn cursor_sequence() -> Result<()> {
62        let data = [10, 20, 30];
63        let mut stream = TokenStream::new(&data);
64
65        verify_that!(stream.pos(), eq(0))?;
66        verify_that!(stream.is_empty(), eq(false))?;
67        verify_that!(stream.len(), eq(3))?;
68        verify_that!(stream.remaining(), eq(&[10, 20, 30]))?;
69
70        verify_that!(stream.peek(), some(eq(&10)))?;
71        verify_that!(stream.pos(), eq(0))?;
72
73        verify_that!(stream.advance(), some(eq(&10)))?;
74        verify_that!(stream.pos(), eq(1))?;
75        verify_that!(stream.remaining(), eq(&[20, 30]))?;
76
77        verify_that!(stream.advance(), some(eq(&20)))?;
78        verify_that!(stream.advance(), some(eq(&30)))?;
79        verify_that!(stream.pos(), eq(3))?;
80        verify_that!(stream.is_empty(), eq(true))?;
81
82        verify_that!(stream.advance(), none())?;
83
84        verify_that!(stream.pos(), eq(3))
85    }
86
87    #[gtest]
88    fn empty_stream() -> Result<()> {
89        let data: [i32; 0] = [];
90        let mut stream = TokenStream::new(&data);
91
92        verify_that!(stream.peek(), none())?;
93        verify_that!(stream.advance(), none())?;
94        verify_that!(stream.is_empty(), eq(true))?;
95
96        verify_that!(stream.remaining(), eq(&[] as &[i32]))
97    }
98}