Move next_can_be_plain_scalar to Input trait.

This commit is contained in:
Ethiraric 2024-07-10 19:17:32 +02:00
parent 8d7c3a1c1b
commit 696ca59a16
3 changed files with 42 additions and 31 deletions

View file

@ -4,7 +4,7 @@ pub mod str;
#[allow(clippy::module_name_repetitions)] #[allow(clippy::module_name_repetitions)]
pub use buffered::BufferedInput; pub use buffered::BufferedInput;
use crate::char_traits::{is_blank_or_breakz, is_breakz}; use crate::char_traits::{is_blank_or_breakz, is_breakz, is_flow};
/// Interface for a source of characters. /// Interface for a source of characters.
/// ///
@ -215,6 +215,21 @@ pub trait Input {
Ok(SkipTabs::Result(encountered_tab, has_yaml_ws)), Ok(SkipTabs::Result(encountered_tab, has_yaml_ws)),
) )
} }
/// Check whether the next characters may be part of a plain scalar.
///
/// This function assumes we are not given a blankz character.
#[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() {
// indicators can end a plain scalar, see 7.3.3. Plain Style
':' if is_blank_or_breakz(nc) || (in_flow && is_flow(nc)) => false,
c if in_flow && is_flow(c) => false,
_ => true,
}
}
} }
/// Behavior to adopt regarding treating tabs as whitespace. /// Behavior to adopt regarding treating tabs as whitespace.

View file

@ -1,5 +1,5 @@
use crate::{ use crate::{
char_traits::{is_blank_or_breakz, is_breakz}, char_traits::{is_blank_or_breakz, is_breakz, is_flow},
input::{Input, SkipTabs}, input::{Input, SkipTabs},
}; };
@ -248,6 +248,28 @@ impl<'a> Input for StrInput<'a> {
Ok(SkipTabs::Result(encountered_tab, has_yaml_ws)), 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 c = self.buffer.as_bytes()[0];
if self.buffer.len() > 1 {
let nc = self.buffer.as_bytes()[1];
match c {
// indicators can end a plain scalar, see 7.3.3. Plain Style
b':' if is_blank_or_breakz(nc as char) || (in_flow && is_flow(nc as char)) => false,
c if in_flow && is_flow(c as char) => false,
_ => true,
}
} else {
match c {
// indicators can end a plain scalar, see 7.3.3. Plain Style
b':' => false,
c if in_flow && is_flow(c as char) => false,
_ => true,
}
}
}
} }
/// The buffer size we return to the scanner. /// The buffer size we return to the scanner.

View file

@ -2119,11 +2119,7 @@ impl<T: Input> Scanner<T> {
} }
if !is_blank_or_breakz(self.input.peek()) if !is_blank_or_breakz(self.input.peek())
&& next_can_be_plain_scalar( && self.input.next_can_be_plain_scalar(self.flow_level > 0)
self.input.peek(),
self.input.peek_nth(1),
self.flow_level > 0,
)
{ {
if self.leading_whitespace { if self.leading_whitespace {
if leading_break.is_empty() { if leading_break.is_empty() {
@ -2159,20 +2155,13 @@ impl<T: Input> Scanner<T> {
// hence the `for` loop looping `self.input.bufmaxlen() - 1` times. // hence the `for` loop looping `self.input.bufmaxlen() - 1` times.
self.input.lookahead(self.input.bufmaxlen()); self.input.lookahead(self.input.bufmaxlen());
for _ in 0..self.input.bufmaxlen() - 1 { for _ in 0..self.input.bufmaxlen() - 1 {
// We need to have `c` and `nc`'s assignations at the beginning of the
// loop. If at the end of it, we will peek one index further than we
// looked ahead. On the first iteration of the loop, `c` is a characte we
// already pushed in `string` a bit earlier.
if is_blank_or_breakz(self.input.peek()) if is_blank_or_breakz(self.input.peek())
|| !next_can_be_plain_scalar( || !self.input.next_can_be_plain_scalar(self.flow_level > 0)
self.input.peek(),
self.input.peek_nth(1),
self.flow_level > 0,
)
{ {
end = true; end = true;
break; break;
} }
assert!(string.len() < string.capacity());
string.push(self.input.peek()); string.push(self.input.peek());
self.skip_non_blank(); self.skip_non_blank();
} }
@ -2531,21 +2520,6 @@ pub enum Chomping {
Keep, Keep,
} }
/// Check whether the next characters may be part of a plain scalar.
///
/// This function assumes we are not given a blankz character.
// For some reason, `#[inline]` is not enough.
#[allow(clippy::inline_always)]
#[inline(always)]
pub fn next_can_be_plain_scalar(c: char, nc: char, in_flow: bool) -> bool {
match c {
// indicators can end a plain scalar, see 7.3.3. Plain Style
':' if is_blank_or_breakz(nc) || (in_flow && is_flow(nc)) => false,
c if in_flow && is_flow(c) => false,
_ => true,
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
#[test] #[test]