Performance improvement.
The refactoring added `next_is` which takes a `&str` as parameter, while we only use it with strings of lengths 2 and 3. Replacing this by 2 dedicated methods (which can be added to the trait interface and only specialized if needed) removes almost all the overhead that was added by `Input`.
This commit is contained in:
parent
d9bb7a1693
commit
f8b6d849d3
3 changed files with 23 additions and 14 deletions
|
@ -90,10 +90,4 @@ impl<T: Iterator<Item = char>> Input for BufferedInput<T> {
|
|||
fn peek_nth(&self, n: usize) -> char {
|
||||
self.buffer[n]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn next_is(&self, pat: &str) -> bool {
|
||||
assert!(self.buffer.len() >= pat.len());
|
||||
self.buffer.iter().zip(pat.chars()).all(|(a, b)| *a == b)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,10 +102,25 @@ pub trait Input {
|
|||
self.peek_nth(n) == c
|
||||
}
|
||||
|
||||
/// Return whether the next characters in the input source match the given pattern.
|
||||
/// Return whether the next 2 characters in the input source match the given characters.
|
||||
///
|
||||
/// This function assumes that the next `pat.len()` characters in the input has already been
|
||||
/// fetched through [`Input::lookahead`].
|
||||
/// This function assumes that the next 2 characters in the input has already been fetched
|
||||
/// through [`Input::lookahead`].
|
||||
#[inline]
|
||||
#[must_use]
|
||||
fn next_is(&self, pat: &str) -> bool;
|
||||
fn next_2_are(&self, c1: char, c2: char) -> bool {
|
||||
assert!(self.buflen() >= 2);
|
||||
self.peek() == c1 && self.peek_nth(1) == c2
|
||||
}
|
||||
|
||||
/// Return whether the next 3 characters in the input source match the given characters.
|
||||
///
|
||||
/// This function assumes that the next 3 characters in the input has already been fetched
|
||||
/// through [`Input::lookahead`].
|
||||
#[inline]
|
||||
#[must_use]
|
||||
fn next_3_are(&self, c1: char, c2: char, c3: char) -> bool {
|
||||
assert!(self.buflen() >= 3);
|
||||
self.peek() == c1 && self.peek_nth(1) == c2 && self.peek_nth(2) == c3
|
||||
}
|
||||
}
|
||||
|
|
|
@ -528,7 +528,7 @@ impl<T: Input> Scanner<T> {
|
|||
/// Consume a linebreak (either CR, LF or CRLF), if any. Do nothing if there's none.
|
||||
#[inline]
|
||||
fn skip_linebreak(&mut self) {
|
||||
if self.input.next_is("\r\n") {
|
||||
if self.input.next_2_are('\r', '\n') {
|
||||
// While technically not a blank, this does not matter as `self.leading_whitespace`
|
||||
// will be reset by `skip_nl`.
|
||||
self.skip_blank();
|
||||
|
@ -597,7 +597,7 @@ impl<T: Input> Scanner<T> {
|
|||
/// [`Self::lookahead`] must have been called before calling this function.
|
||||
fn next_is_document_start(&self) -> bool {
|
||||
assert!(self.input.buflen() >= 4);
|
||||
self.input.next_is("---") && is_blank_or_breakz(self.input.peek_nth(3))
|
||||
self.input.next_3_are('-', '-', '-') && is_blank_or_breakz(self.input.peek_nth(3))
|
||||
}
|
||||
|
||||
/// Check whether the next characters correspond to an end of document.
|
||||
|
@ -605,7 +605,7 @@ impl<T: Input> Scanner<T> {
|
|||
/// [`Self::lookahead`] must have been called before calling this function.
|
||||
fn next_is_document_end(&self) -> bool {
|
||||
assert!(self.input.buflen() >= 4);
|
||||
self.input.next_is("...") && is_blank_or_breakz(self.input.peek_nth(3))
|
||||
self.input.next_3_are('.', '.', '.') && is_blank_or_breakz(self.input.peek_nth(3))
|
||||
}
|
||||
|
||||
/// Check whether the next characters correspond to a document indicator.
|
||||
|
@ -615,7 +615,7 @@ impl<T: Input> Scanner<T> {
|
|||
fn next_is_document_indicator(&self) -> bool {
|
||||
assert!(self.input.buflen() >= 4);
|
||||
is_blank_or_breakz(self.input.peek_nth(3))
|
||||
&& (self.input.next_is("...") || self.input.next_is("---"))
|
||||
&& (self.input.next_3_are('.', '.', '.') || self.input.next_3_are('-', '-', '-'))
|
||||
}
|
||||
|
||||
/// Insert a token at the given position.
|
||||
|
|
Loading…
Reference in a new issue