From 9b13d54e44a24ddea71823207747c6aeead765f3 Mon Sep 17 00:00:00 2001 From: Bazaah Date: Thu, 9 Sep 2021 12:06:25 +0000 Subject: [PATCH] scanner/macros: add cache! cache! allows the Scanner to state that it requires 'N' more codepoints before it can correctly process the byte stream. Its primary purpose is its interaction with O_EXTENDABLE, which allows the caller to hint to the Scanner that the buffer could grow, likewise cache! returns an error that hints to the caller that they should extend the byte stream before calling the Scanner again -- or pass opts without O_EXTENDABLE. --- src/scanner/macros.rs | 54 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/scanner/macros.rs b/src/scanner/macros.rs index a95801b..32fc0ef 100644 --- a/src/scanner/macros.rs +++ b/src/scanner/macros.rs @@ -87,6 +87,60 @@ macro_rules! cow { }; } +/// Check that the underlying .buffer has at least the given +/// number of UTF8 .codepoints available, returning an error +/// if O_EXTENDABLE is set in .opts. Returns the number of +/// _bytes_ read. +/// +/// Modifiers +/// ~ .buffer := .buffer.as_bytes() +/// +/// Variants +/// /1 .buffer, .codepoints +/// := /4 .buffer, @0, .codepoints, O_ZEROED +/// /2 .buffer, @.offset, .codepoints +/// := /4 .buffer, @.offset, .codepoints, O_ZEROED +/// /3 .buffer, .codepoints, .opts +/// := /4 .buffer @0, .codepoints, .opts +/// /4 .buffer, @.offset, .codepoints, .opts +macro_rules! cache { + (~$buffer:expr $(, @$offset:expr )?, $codepoints:expr $(, $opts:expr )?) => { + cache!($buffer.as_bytes(), $( @$offset, )? $codepoints $(, $opts )?) + }; + ($buffer:expr $(, @$offset:expr )?, $codepoints:expr $(, $opts:expr )?) => { + cache!(@inner $buffer, $( @$offset, )? @0, $codepoints $(, $opts )?, $crate::scanner::flag::O_ZEROED) + }; + (@inner $buffer:expr, @$offset:expr, $( @$_:expr, )? $codepoints:expr, $opts:expr $(, $__:expr )?) => { + cache!(@priv $buffer, $offset, $codepoints, $opts.contains($crate::scanner::flag::O_EXTENDABLE)) + }; + (@priv $buffer:expr, $offset:expr, $codepoints:expr, $extend:expr) => {{ + let mut ret = Ok(0); + let mut bytes = $offset; + for _ in 0..$codepoints + { + match widthOf!($buffer, bytes) + { + 0 => + { + if $extend + { + ret = Err($crate::scanner::error::ScanError::Extend); + } + + break; + }, + n => + { + bytes += n; + ret = ret.map(|r| r + n); + }, + } + } + + ret + }}; +} + /// Check the .buffer (@ .offset) matches the given /// .pattern, optionally returning an .error. ///