scanner/directive: cache! before fetch
This commit is contained in:
parent
55b8f31b7b
commit
dc10680862
|
@ -5,13 +5,14 @@ use super::{
|
||||||
stats::MStats,
|
stats::MStats,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
scanner::{eat_whitespace, tag::scan_tag_directive, COMMENTS},
|
scanner::{eat_whitespace, flag::Flags, tag::scan_tag_directive, COMMENTS},
|
||||||
token::Token,
|
token::Token,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Scans a version or tag directive from .buffer, based on
|
/// Scans a version or tag directive from .buffer, based on
|
||||||
/// the .kind of directive, returning the relevant Token.
|
/// the .kind of directive, returning the relevant Token.
|
||||||
pub(in crate::scanner) fn scan_directive<'de>(
|
pub(in crate::scanner) fn scan_directive<'de>(
|
||||||
|
opts: Flags,
|
||||||
buffer: &mut &'de str,
|
buffer: &mut &'de str,
|
||||||
mut stats: &mut MStats,
|
mut stats: &mut MStats,
|
||||||
kind: &DirectiveKind,
|
kind: &DirectiveKind,
|
||||||
|
@ -22,21 +23,25 @@ pub(in crate::scanner) fn scan_directive<'de>(
|
||||||
DirectiveKind::Version =>
|
DirectiveKind::Version =>
|
||||||
{
|
{
|
||||||
// Chomp any preceding whitespace
|
// Chomp any preceding whitespace
|
||||||
advance!(*buffer, eat_whitespace(buffer, &mut stats, !COMMENTS));
|
advance!(
|
||||||
|
*buffer,
|
||||||
|
eat_whitespace(opts, buffer, &mut stats, !COMMENTS)?
|
||||||
|
);
|
||||||
|
|
||||||
// %YAML 1.1
|
// %YAML 1.1
|
||||||
// ^
|
// ^
|
||||||
let (major, skip) = scan_directive_version(buffer)?;
|
let (major, skip) = scan_directive_version(opts, buffer)?;
|
||||||
advance!(*buffer, :stats, skip);
|
advance!(*buffer, :stats, skip);
|
||||||
|
|
||||||
// %YAML 1.1
|
// %YAML 1.1
|
||||||
// ^
|
// ^
|
||||||
|
cache!(~buffer, 1, opts)?;
|
||||||
check!(~buffer => b'.', else ScanError::InvalidVersion)?;
|
check!(~buffer => b'.', else ScanError::InvalidVersion)?;
|
||||||
advance!(*buffer, :stats, 1);
|
advance!(*buffer, :stats, 1);
|
||||||
|
|
||||||
// %YAML 1.1
|
// %YAML 1.1
|
||||||
// ^
|
// ^
|
||||||
let (minor, skip) = scan_directive_version(buffer)?;
|
let (minor, skip) = scan_directive_version(opts, buffer)?;
|
||||||
advance!(*buffer, :stats, skip);
|
advance!(*buffer, :stats, skip);
|
||||||
|
|
||||||
Ok(Token::VersionDirective(major, minor))
|
Ok(Token::VersionDirective(major, minor))
|
||||||
|
@ -44,10 +49,13 @@ pub(in crate::scanner) fn scan_directive<'de>(
|
||||||
DirectiveKind::Tag =>
|
DirectiveKind::Tag =>
|
||||||
{
|
{
|
||||||
// Chomp any spaces up to the handle
|
// Chomp any spaces up to the handle
|
||||||
advance!(*buffer, eat_whitespace(buffer, &mut stats, !COMMENTS));
|
advance!(
|
||||||
|
*buffer,
|
||||||
|
eat_whitespace(opts, buffer, &mut stats, !COMMENTS)?
|
||||||
|
);
|
||||||
|
|
||||||
// Scan the directive, copying if necessary
|
// Scan the directive, copying if necessary
|
||||||
let (token, amt) = scan_tag_directive(buffer, &mut stats)?;
|
let (token, amt) = scan_tag_directive(opts, buffer, &mut stats)?;
|
||||||
advance!(*buffer, amt);
|
advance!(*buffer, amt);
|
||||||
|
|
||||||
Ok(token)
|
Ok(token)
|
||||||
|
@ -97,15 +105,15 @@ impl DirectiveKind
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scan_directive_version(b: &str) -> Result<(u8, usize)>
|
fn scan_directive_version(opts: Flags, b: &str) -> Result<(u8, usize)>
|
||||||
{
|
{
|
||||||
let v_slice = take_while(b.as_bytes(), u8::is_ascii_digit);
|
let v_slice = take_while(opts, b.as_bytes(), u8::is_ascii_digit)?;
|
||||||
let v = atoi(v_slice).ok_or(ScanError::InvalidVersion)?;
|
let v = atoi(v_slice).ok_or(ScanError::InvalidVersion)?;
|
||||||
|
|
||||||
Ok((v, v_slice.len()))
|
Ok((v, v_slice.len()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn take_while<F>(b: &[u8], f: F) -> &[u8]
|
fn take_while<F>(opts: Flags, base: &[u8], f: F) -> Result<&[u8]>
|
||||||
where
|
where
|
||||||
F: Fn(&u8) -> bool,
|
F: Fn(&u8) -> bool,
|
||||||
{
|
{
|
||||||
|
@ -113,10 +121,12 @@ where
|
||||||
|
|
||||||
loop
|
loop
|
||||||
{
|
{
|
||||||
match b.get(index)
|
let i = cache!(base, @index, 1, opts)?;
|
||||||
|
|
||||||
|
match base.get(index)
|
||||||
{
|
{
|
||||||
Some(b) if f(b) => index += 1,
|
Some(b) if f(b) => index += i,
|
||||||
_ => return &b[..index],
|
_ => return Ok(&base[..index]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,7 +135,7 @@ impl Scanner
|
||||||
match base.as_bytes()
|
match base.as_bytes()
|
||||||
{
|
{
|
||||||
// Is it a directive?
|
// Is it a directive?
|
||||||
[DIRECTIVE, ..] if self.stats.column == 0 => self.fetch_directive(base, tokens),
|
[DIRECTIVE, ..] if self.stats.column == 0 => self.fetch_directive(opts, base, tokens),
|
||||||
|
|
||||||
// Is it a document marker?
|
// Is it a document marker?
|
||||||
[b @ b'-', b'-', b'-', ..] | [b @ b'.', b'.', b'.', ..]
|
[b @ b'-', b'-', b'-', ..] | [b @ b'.', b'.', b'.', ..]
|
||||||
|
@ -270,8 +270,12 @@ impl Scanner
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_directive<'de>(&mut self, base: &mut &'de str, tokens: &mut Tokens<'de>)
|
fn fetch_directive<'de>(
|
||||||
-> Result<()>
|
&mut self,
|
||||||
|
opts: Flags,
|
||||||
|
base: &mut &'de str,
|
||||||
|
tokens: &mut Tokens<'de>,
|
||||||
|
) -> Result<()>
|
||||||
{
|
{
|
||||||
let mut buffer = *base;
|
let mut buffer = *base;
|
||||||
let mut stats = MStats::new();
|
let mut stats = MStats::new();
|
||||||
|
@ -299,7 +303,7 @@ impl Scanner
|
||||||
advance!(buffer, :stats, 1 + kind.len());
|
advance!(buffer, :stats, 1 + kind.len());
|
||||||
|
|
||||||
// Scan the directive token from the .buffer
|
// Scan the directive token from the .buffer
|
||||||
let token = scan_directive(&mut buffer, &mut stats, &kind)?;
|
let token = scan_directive(opts, &mut buffer, &mut stats, &kind)?;
|
||||||
|
|
||||||
// A key cannot follow a directive (a newline is required)
|
// A key cannot follow a directive (a newline is required)
|
||||||
self.simple_key_allowed = false;
|
self.simple_key_allowed = false;
|
||||||
|
|
Loading…
Reference in a new issue