diff --git a/src/scanner/directive.rs b/src/scanner/directive.rs index ee3e00d..91da8f8 100644 --- a/src/scanner/directive.rs +++ b/src/scanner/directive.rs @@ -5,13 +5,14 @@ use super::{ stats::MStats, }; use crate::{ - scanner::{eat_whitespace, tag::scan_tag_directive, COMMENTS}, + scanner::{eat_whitespace, flag::Flags, tag::scan_tag_directive, COMMENTS}, token::Token, }; /// Scans a version or tag directive from .buffer, based on /// the .kind of directive, returning the relevant Token. pub(in crate::scanner) fn scan_directive<'de>( + opts: Flags, buffer: &mut &'de str, mut stats: &mut MStats, kind: &DirectiveKind, @@ -22,21 +23,25 @@ pub(in crate::scanner) fn scan_directive<'de>( DirectiveKind::Version => { // Chomp any preceding whitespace - advance!(*buffer, eat_whitespace(buffer, &mut stats, !COMMENTS)); + advance!( + *buffer, + eat_whitespace(opts, buffer, &mut stats, !COMMENTS)? + ); // %YAML 1.1 // ^ - let (major, skip) = scan_directive_version(buffer)?; + let (major, skip) = scan_directive_version(opts, buffer)?; advance!(*buffer, :stats, skip); // %YAML 1.1 // ^ + cache!(~buffer, 1, opts)?; check!(~buffer => b'.', else ScanError::InvalidVersion)?; advance!(*buffer, :stats, 1); // %YAML 1.1 // ^ - let (minor, skip) = scan_directive_version(buffer)?; + let (minor, skip) = scan_directive_version(opts, buffer)?; advance!(*buffer, :stats, skip); Ok(Token::VersionDirective(major, minor)) @@ -44,10 +49,13 @@ pub(in crate::scanner) fn scan_directive<'de>( DirectiveKind::Tag => { // 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 - let (token, amt) = scan_tag_directive(buffer, &mut stats)?; + let (token, amt) = scan_tag_directive(opts, buffer, &mut stats)?; advance!(*buffer, amt); 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)?; Ok((v, v_slice.len())) } -fn take_while(b: &[u8], f: F) -> &[u8] +fn take_while(opts: Flags, base: &[u8], f: F) -> Result<&[u8]> where F: Fn(&u8) -> bool, { @@ -113,10 +121,12 @@ where loop { - match b.get(index) + let i = cache!(base, @index, 1, opts)?; + + match base.get(index) { - Some(b) if f(b) => index += 1, - _ => return &b[..index], + Some(b) if f(b) => index += i, + _ => return Ok(&base[..index]), } } } diff --git a/src/scanner/mod.rs b/src/scanner/mod.rs index c53a1c1..8778164 100644 --- a/src/scanner/mod.rs +++ b/src/scanner/mod.rs @@ -135,7 +135,7 @@ impl Scanner match base.as_bytes() { // 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? [b @ b'-', b'-', b'-', ..] | [b @ b'.', b'.', b'.', ..] @@ -270,8 +270,12 @@ impl Scanner Ok(()) } - fn fetch_directive<'de>(&mut self, base: &mut &'de str, tokens: &mut Tokens<'de>) - -> Result<()> + fn fetch_directive<'de>( + &mut self, + opts: Flags, + base: &mut &'de str, + tokens: &mut Tokens<'de>, + ) -> Result<()> { let mut buffer = *base; let mut stats = MStats::new(); @@ -299,7 +303,7 @@ impl Scanner advance!(buffer, :stats, 1 + kind.len()); // 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) self.simple_key_allowed = false;