]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_lexer/src/cursor.rs
Auto merge of #77853 - ijackson:slice-strip-stab, r=Amanieu
[rust.git] / compiler / rustc_lexer / src / cursor.rs
1 use std::str::Chars;
2
3 /// Peekable iterator over a char sequence.
4 ///
5 /// Next characters can be peeked via `nth_char` method,
6 /// and position can be shifted forward via `bump` method.
7 pub(crate) struct Cursor<'a> {
8     initial_len: usize,
9     chars: Chars<'a>,
10     #[cfg(debug_assertions)]
11     prev: char,
12 }
13
14 pub(crate) const EOF_CHAR: char = '\0';
15
16 impl<'a> Cursor<'a> {
17     pub(crate) fn new(input: &'a str) -> Cursor<'a> {
18         Cursor {
19             initial_len: input.len(),
20             chars: input.chars(),
21             #[cfg(debug_assertions)]
22             prev: EOF_CHAR,
23         }
24     }
25
26     /// Returns the last eaten symbol (or `'\0'` in release builds).
27     /// (For debug assertions only.)
28     pub(crate) fn prev(&self) -> char {
29         #[cfg(debug_assertions)]
30         {
31             self.prev
32         }
33
34         #[cfg(not(debug_assertions))]
35         {
36             '\0'
37         }
38     }
39
40     /// Returns nth character relative to the current cursor position.
41     /// If requested position doesn't exist, `EOF_CHAR` is returned.
42     /// However, getting `EOF_CHAR` doesn't always mean actual end of file,
43     /// it should be checked with `is_eof` method.
44     fn nth_char(&self, n: usize) -> char {
45         self.chars().nth(n).unwrap_or(EOF_CHAR)
46     }
47
48     /// Peeks the next symbol from the input stream without consuming it.
49     pub(crate) fn first(&self) -> char {
50         self.nth_char(0)
51     }
52
53     /// Peeks the second symbol from the input stream without consuming it.
54     pub(crate) fn second(&self) -> char {
55         self.nth_char(1)
56     }
57
58     /// Checks if there is nothing more to consume.
59     pub(crate) fn is_eof(&self) -> bool {
60         self.chars.as_str().is_empty()
61     }
62
63     /// Returns amount of already consumed symbols.
64     pub(crate) fn len_consumed(&self) -> usize {
65         self.initial_len - self.chars.as_str().len()
66     }
67
68     /// Returns a `Chars` iterator over the remaining characters.
69     fn chars(&self) -> Chars<'a> {
70         self.chars.clone()
71     }
72
73     /// Moves to the next character.
74     pub(crate) fn bump(&mut self) -> Option<char> {
75         let c = self.chars.next()?;
76
77         #[cfg(debug_assertions)]
78         {
79             self.prev = c;
80         }
81
82         Some(c)
83     }
84 }