mirror of
https://github.com/rust-lang/rust.git
synced 2025-10-30 12:36:38 +00:00
From 72 bytes to 12 bytes (on x86-64). There are two parts to this: - Changing various source code offsets from 64-bit to 32-bit. This is not a problem because the rest of rustc also uses 32-bit source code offsets. This means `Token` is no longer `Copy` but this causes no problems. - Removing the `RawStrError` from `LiteralKind`. Raw string literal invalidity is now indicated by a `None` value within `RawStr`/`RawByteStr`, and the new `validate_raw_str` function can be used to re-lex an invalid raw string literal to get the `RawStrError`. There is one very small change in behaviour. Previously, if a raw string literal matched both the `InvalidStarter` and `TooManyHashes` cases, the latter would override the former. This has now changed, because `raw_double_quoted_string` now uses `?` and so returns immediately upon detecting the `InvalidStarter` case. I think this is a slight improvement to report the earlier-detected error, and it explains the change in the `test_too_many_hashes` test. The commit also removes a couple of comments that refer to #77629 and say that the size of these types don't affect performance. These comments are wrong, though the performance effect is small.
94 lines
2.7 KiB
Rust
94 lines
2.7 KiB
Rust
use std::str::Chars;
|
|
|
|
/// Peekable iterator over a char sequence.
|
|
///
|
|
/// Next characters can be peeked via `first` method,
|
|
/// and position can be shifted forward via `bump` method.
|
|
pub(crate) struct Cursor<'a> {
|
|
initial_len: usize,
|
|
/// Iterator over chars. Slightly faster than a &str.
|
|
chars: Chars<'a>,
|
|
#[cfg(debug_assertions)]
|
|
prev: char,
|
|
}
|
|
|
|
pub(crate) const EOF_CHAR: char = '\0';
|
|
|
|
impl<'a> Cursor<'a> {
|
|
pub(crate) fn new(input: &'a str) -> Cursor<'a> {
|
|
Cursor {
|
|
initial_len: input.len(),
|
|
chars: input.chars(),
|
|
#[cfg(debug_assertions)]
|
|
prev: EOF_CHAR,
|
|
}
|
|
}
|
|
|
|
/// Returns the last eaten symbol (or `'\0'` in release builds).
|
|
/// (For debug assertions only.)
|
|
pub(crate) fn prev(&self) -> char {
|
|
#[cfg(debug_assertions)]
|
|
{
|
|
self.prev
|
|
}
|
|
|
|
#[cfg(not(debug_assertions))]
|
|
{
|
|
EOF_CHAR
|
|
}
|
|
}
|
|
|
|
/// Peeks the next symbol from the input stream without consuming it.
|
|
/// If requested position doesn't exist, `EOF_CHAR` is returned.
|
|
/// However, getting `EOF_CHAR` doesn't always mean actual end of file,
|
|
/// it should be checked with `is_eof` method.
|
|
pub(crate) fn first(&self) -> char {
|
|
// `.next()` optimizes better than `.nth(0)`
|
|
self.chars.clone().next().unwrap_or(EOF_CHAR)
|
|
}
|
|
|
|
/// Peeks the second symbol from the input stream without consuming it.
|
|
pub(crate) fn second(&self) -> char {
|
|
// `.next()` optimizes better than `.nth(1)`
|
|
let mut iter = self.chars.clone();
|
|
iter.next();
|
|
iter.next().unwrap_or(EOF_CHAR)
|
|
}
|
|
|
|
/// Checks if there is nothing more to consume.
|
|
pub(crate) fn is_eof(&self) -> bool {
|
|
self.chars.as_str().is_empty()
|
|
}
|
|
|
|
/// Returns amount of already consumed symbols.
|
|
pub(crate) fn len_consumed(&self) -> u32 {
|
|
(self.initial_len - self.chars.as_str().len()) as u32
|
|
}
|
|
|
|
/// Resets the number of bytes consumed to 0.
|
|
pub(crate) fn reset_len_consumed(&mut self) {
|
|
self.initial_len = self.chars.as_str().len();
|
|
}
|
|
|
|
/// Moves to the next character.
|
|
pub(crate) fn bump(&mut self) -> Option<char> {
|
|
let c = self.chars.next()?;
|
|
|
|
#[cfg(debug_assertions)]
|
|
{
|
|
self.prev = c;
|
|
}
|
|
|
|
Some(c)
|
|
}
|
|
|
|
/// Eats symbols while predicate returns true or until the end of file is reached.
|
|
pub(crate) fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) {
|
|
// It was tried making optimized version of this for eg. line comments, but
|
|
// LLVM can inline all of this and compile it down to fast iteration over bytes.
|
|
while predicate(self.first()) && !self.is_eof() {
|
|
self.bump();
|
|
}
|
|
}
|
|
}
|