3 /// Peekable iterator over a char sequence.
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> {
10 #[cfg(debug_assertions)]
14 pub(crate) const EOF_CHAR: char = '\0';
17 pub(crate) fn new(input: &'a str) -> Cursor<'a> {
19 initial_len: input.len(),
21 #[cfg(debug_assertions)]
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)]
34 #[cfg(not(debug_assertions))]
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)
48 /// Peeks the next symbol from the input stream without consuming it.
49 pub(crate) fn first(&self) -> char {
53 /// Peeks the second symbol from the input stream without consuming it.
54 pub(crate) fn second(&self) -> char {
58 /// Checks if there is nothing more to consume.
59 pub(crate) fn is_eof(&self) -> bool {
60 self.chars.as_str().is_empty()
63 /// Returns amount of already consumed symbols.
64 pub(crate) fn len_consumed(&self) -> usize {
65 self.initial_len - self.chars.as_str().len()
68 /// Returns a `Chars` iterator over the remaining characters.
69 fn chars(&self) -> Chars<'a> {
73 /// Moves to the next character.
74 pub(crate) fn bump(&mut self) -> Option<char> {
75 let c = self.chars.next()?;
77 #[cfg(debug_assertions)]