2024-04-18 15:48:49 +00:00
|
|
|
/// Interface for a source of characters.
|
|
|
|
///
|
|
|
|
/// Hiding the input's implementation behind this trait allows mostly:
|
|
|
|
/// * For input-specific optimizations (for instance, using `str` methods instead of manually
|
|
|
|
/// transferring one `char` at a time to a buffer).
|
|
|
|
/// * To return `&str`s referencing the input string, thus avoiding potentially costly
|
|
|
|
/// allocations. Should users need an owned version of the data, they can always `.to_owned()`
|
|
|
|
/// their YAML object.
|
|
|
|
pub trait Input {
|
|
|
|
/// A hint to the input source that we will need to read `count` characters.
|
|
|
|
///
|
|
|
|
/// If the input is exhausted, `\0` can be used to pad the last characters and later returned.
|
|
|
|
/// The characters must not be consumed, but may be placed in an internal buffer.
|
|
|
|
///
|
|
|
|
/// This method may be a no-op if buffering yields no performance improvement.
|
|
|
|
///
|
|
|
|
/// Implementers of [`Input`] must _not_ load more than `count` characters into the buffer. The
|
|
|
|
/// parser tracks how many characters are loaded in the buffer and acts accordingly.
|
|
|
|
fn lookahead(&mut self, count: usize);
|
|
|
|
|
|
|
|
/// Return the number of buffered characters in `self`.
|
|
|
|
#[must_use]
|
|
|
|
fn buflen(&self) -> usize;
|
|
|
|
|
|
|
|
/// Return the capacity of the buffer in `self`.
|
|
|
|
#[must_use]
|
|
|
|
fn bufmaxlen(&self) -> usize;
|
|
|
|
|
|
|
|
/// Return whether the buffer (!= stream) is empty.
|
|
|
|
#[inline]
|
|
|
|
#[must_use]
|
|
|
|
fn buf_is_empty(&self) -> bool {
|
|
|
|
self.buflen() == 0
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Read a character from the input stream and return it directly.
|
|
|
|
///
|
|
|
|
/// The internal buffer (is any) is bypassed.
|
|
|
|
#[must_use]
|
|
|
|
fn raw_read_ch(&mut self) -> char;
|
|
|
|
|
|
|
|
/// Put a character back in the buffer.
|
|
|
|
///
|
|
|
|
/// This function is only called when we read one too many characters and the pushed back
|
|
|
|
/// character is exactly the last character that was read. This function will not be called
|
|
|
|
/// multiple times consecutively.
|
|
|
|
fn push_back(&mut self, c: char);
|
|
|
|
|
|
|
|
/// Consume the next character.
|
|
|
|
fn skip(&mut self);
|
|
|
|
|
|
|
|
/// Consume the next `count` character.
|
|
|
|
fn skip_n(&mut self, count: usize);
|
|
|
|
|
|
|
|
/// Return the next character, without consuming it.
|
|
|
|
///
|
|
|
|
/// Users of the [`Input`] must make sure that the character has been loaded through a prior
|
|
|
|
/// call to [`Input::lookahead`]. Implementors of [`Input`] may assume that a valid call to
|
|
|
|
/// [`Input::lookahead`] has been made beforehand.
|
|
|
|
///
|
|
|
|
/// # Return
|
|
|
|
/// If the input source is not exhausted, returns the next character to be fed into the
|
|
|
|
/// scanner. Otherwise, returns `\0`.
|
|
|
|
#[must_use]
|
|
|
|
fn peek(&self) -> char;
|
|
|
|
|
|
|
|
/// Return the `n`-th character in the buffer, without consuming it.
|
|
|
|
///
|
|
|
|
/// This function assumes that the n-th character in the input has already been fetched through
|
|
|
|
/// [`Input::lookahead`].
|
|
|
|
#[must_use]
|
|
|
|
fn peek_nth(&self, n: usize) -> char;
|
|
|
|
|
|
|
|
/// Look for the next character and return it.
|
|
|
|
///
|
|
|
|
/// The character is not consumed.
|
|
|
|
/// Equivalent to calling [`Input::lookahead`] and [`Input::peek`].
|
|
|
|
#[inline]
|
|
|
|
#[must_use]
|
|
|
|
fn look_ch(&mut self) -> char {
|
|
|
|
self.lookahead(1);
|
|
|
|
self.peek()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return whether the next character in the input source is equal to `c`.
|
|
|
|
///
|
|
|
|
/// This function assumes that the next character in the input has already been fetched through
|
|
|
|
/// [`Input::lookahead`].
|
|
|
|
#[inline]
|
|
|
|
#[must_use]
|
|
|
|
fn next_char_is(&self, c: char) -> bool {
|
|
|
|
self.peek() == c
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return whether the `n`-th character in the input source is equal to `c`.
|
|
|
|
///
|
|
|
|
/// This function assumes that the n-th character in the input has already been fetched through
|
|
|
|
/// [`Input::lookahead`].
|
|
|
|
#[inline]
|
|
|
|
#[must_use]
|
|
|
|
fn nth_char_is(&self, n: usize, c: char) -> bool {
|
|
|
|
self.peek_nth(n) == c
|
|
|
|
}
|
|
|
|
|
2024-04-18 17:11:40 +00:00
|
|
|
/// Return whether the next 2 characters in the input source match the given characters.
|
2024-04-18 15:48:49 +00:00
|
|
|
///
|
2024-04-18 17:11:40 +00:00
|
|
|
/// This function assumes that the next 2 characters in the input has already been fetched
|
|
|
|
/// through [`Input::lookahead`].
|
|
|
|
#[inline]
|
2024-04-18 15:48:49 +00:00
|
|
|
#[must_use]
|
2024-04-18 17:11:40 +00:00
|
|
|
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
|
|
|
|
}
|
2024-04-18 15:48:49 +00:00
|
|
|
}
|