pub(crate) mod buffered;
pub(crate) mod str;
#[allow(clippy::module_name_repetitions)]
pub use buffered::BufferedInput;
pub use crate::char_traits::{
is_alpha, is_blank, is_blank_or_breakz, is_break, is_breakz, is_digit, is_flow, is_z,
};
pub trait Input {
fn lookahead(&mut self, count: usize);
#[must_use]
fn buflen(&self) -> usize;
#[must_use]
fn bufmaxlen(&self) -> usize;
#[inline]
#[must_use]
fn buf_is_empty(&self) -> bool {
self.buflen() == 0
}
#[must_use]
fn raw_read_ch(&mut self) -> char;
#[must_use]
fn raw_read_non_breakz_ch(&mut self) -> Option<char>;
fn skip(&mut self);
fn skip_n(&mut self, count: usize);
#[must_use]
fn peek(&self) -> char;
#[must_use]
fn peek_nth(&self, n: usize) -> char;
#[inline]
#[must_use]
fn look_ch(&mut self) -> char {
self.lookahead(1);
self.peek()
}
#[inline]
#[must_use]
fn next_char_is(&self, c: char) -> bool {
self.peek() == c
}
#[inline]
#[must_use]
fn nth_char_is(&self, n: usize, c: char) -> bool {
self.peek_nth(n) == c
}
#[inline]
#[must_use]
fn next_2_are(&self, c1: char, c2: char) -> bool {
assert!(self.buflen() >= 2);
self.peek() == c1 && self.peek_nth(1) == c2
}
#[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
}
#[inline]
#[must_use]
fn next_is_document_indicator(&self) -> bool {
assert!(self.buflen() >= 4);
is_blank_or_breakz(self.peek_nth(3))
&& (self.next_3_are('.', '.', '.') || self.next_3_are('-', '-', '-'))
}
#[inline]
#[must_use]
fn next_is_document_start(&self) -> bool {
assert!(self.buflen() >= 4);
self.next_3_are('-', '-', '-') && is_blank_or_breakz(self.peek_nth(3))
}
#[inline]
#[must_use]
fn next_is_document_end(&self) -> bool {
assert!(self.buflen() >= 4);
self.next_3_are('.', '.', '.') && is_blank_or_breakz(self.peek_nth(3))
}
fn skip_ws_to_eol(&mut self, skip_tabs: SkipTabs) -> (usize, Result<SkipTabs, &'static str>) {
let mut encountered_tab = false;
let mut has_yaml_ws = false;
let mut chars_consumed = 0;
loop {
match self.look_ch() {
' ' => {
has_yaml_ws = true;
self.skip();
}
'\t' if skip_tabs != SkipTabs::No => {
encountered_tab = true;
self.skip();
}
'#' if !encountered_tab && !has_yaml_ws => {
return (
chars_consumed,
Err("comments must be separated from other tokens by whitespace"),
);
}
'#' => {
self.skip(); while !is_breakz(self.look_ch()) {
self.skip();
chars_consumed += 1;
}
}
_ => break,
}
chars_consumed += 1;
}
(
chars_consumed,
Ok(SkipTabs::Result(encountered_tab, has_yaml_ws)),
)
}
#[allow(clippy::inline_always)]
#[inline(always)]
fn next_can_be_plain_scalar(&self, in_flow: bool) -> bool {
let nc = self.peek_nth(1);
match self.peek() {
':' if is_blank_or_breakz(nc) || (in_flow && is_flow(nc)) => false,
c if in_flow && is_flow(c) => false,
_ => true,
}
}
#[inline]
fn next_is_blank_or_break(&self) -> bool {
is_blank(self.peek()) || is_break(self.peek())
}
#[inline]
fn next_is_blank_or_breakz(&self) -> bool {
is_blank(self.peek()) || is_breakz(self.peek())
}
#[inline]
fn next_is_blank(&self) -> bool {
is_blank(self.peek())
}
#[inline]
fn next_is_break(&self) -> bool {
is_break(self.peek())
}
#[inline]
fn next_is_breakz(&self) -> bool {
is_breakz(self.peek())
}
#[inline]
fn next_is_z(&self) -> bool {
is_z(self.peek())
}
#[inline]
fn next_is_flow(&self) -> bool {
is_flow(self.peek())
}
#[inline]
fn next_is_digit(&self) -> bool {
is_digit(self.peek())
}
#[inline]
fn next_is_alpha(&self) -> bool {
is_alpha(self.peek())
}
#[inline]
fn skip_while_non_breakz(&mut self) -> usize {
let mut count = 0;
while !is_breakz(self.look_ch()) {
count += 1;
self.skip();
}
count
}
fn skip_while_blank(&mut self) -> usize {
let mut n_chars = 0;
while is_blank(self.look_ch()) {
n_chars += 1;
self.skip();
}
n_chars
}
fn fetch_while_is_alpha(&mut self, out: &mut String) -> usize {
let mut n_chars = 0;
while is_alpha(self.look_ch()) {
n_chars += 1;
out.push(self.peek());
self.skip();
}
n_chars
}
}
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum SkipTabs {
Yes,
No,
Result(
bool,
bool,
),
}
impl SkipTabs {
#[must_use]
pub fn found_tabs(self) -> bool {
matches!(self, SkipTabs::Result(true, _))
}
#[must_use]
pub fn has_valid_yaml_ws(self) -> bool {
matches!(self, SkipTabs::Result(_, true))
}
}