use super::Lexer;
impl Lexer {
#[inline]
pub(super) fn decode_char_at(&self, pos: usize) -> (char, usize) {
if pos >= self.input.len() {
return ('\0', 0);
}
let b = self.input[pos];
if b < 0x80 {
return (b as char, 1);
}
let width = match b {
0xC2..=0xDF => 2,
0xE0..=0xEF => 3,
0xF0..=0xF4 => 4,
_ => return ('\u{FFFD}', 1),
};
let Some(end) = pos
.checked_add(width)
.filter(|&end| end <= self.input.len())
else {
return ('\u{FFFD}', 1);
};
match std::str::from_utf8(&self.input[pos..end]) {
Ok(s) => (s.chars().next().unwrap_or('\u{FFFD}'), width),
Err(_) => ('\u{FFFD}', 1),
}
}
pub(super) fn read_char(&mut self) {
if !self.eof && self.ch == '\n' {
self.pos.line += 1;
self.pos.column = 1;
} else if !self.eof {
self.pos.column += 1;
}
if self.read_position >= self.input.len() {
self.ch = '\0'; self.position = self.read_position;
self.eof = true;
} else {
let (ch, len) = self.decode_char_at(self.read_position);
self.ch = ch;
self.position = self.read_position;
self.read_position += len;
self.eof = false;
}
self.pos.offset = self.position;
}
#[inline]
pub(super) fn peek_char(&self) -> char {
self.decode_char_at(self.read_position).0
}
pub(super) fn skip_whitespace(&mut self) {
while self.ch.is_whitespace() {
if self.ch == '\r' && self.peek_char() == '\n' {
self.read_char(); }
self.read_char();
}
}
}