@ -11,6 +11,8 @@ use std::io::Write;
pub struct Parser {
token : & 'static [ u8 ] ,
suffix : & 'static [ u8 ] ,
/// NORA: Records the position in the token across calls to `process`.
pos : usize ,
}
impl Parser {
@ -19,7 +21,11 @@ impl Parser {
//
// NOTE: This function signature should stay the same.
pub fn new ( token : & 'static [ u8 ] , suffix : & 'static [ u8 ] ) -> Self {
Self { token , suffix }
Self {
token ,
suffix ,
pos : 0 ,
}
}
/// Write the bytes given in `input` to `output`, plus the bytes in `suffix`
@ -56,7 +62,42 @@ impl Parser {
//
// NOTE: This function signature should stay the same.
pub fn process ( & mut self , input : & [ u8 ] , output : & mut dyn Write ) -> Result < ( ) , std ::io ::Error > {
output . write_all ( input )
// NORA: Create a buffer to work in for just this call.
// We'll write the whole buffer at the end, unconditionally;
// the only question is what's in it.
let mut buffer = Vec ::with_capacity ( input . len ( ) + self . suffix . len ( ) ) ;
// NORA: Look at each byte in the input.
for byte in input {
// NORA: Unconditionally, write that byte into our buffer.
// No requirement calls for losing any bytes.
buffer . push ( * byte ) ;
// NORA: Compare the current byte in the input to the current byte
// in the token.
if * byte = = self . token [ self . pos ] {
// NORA: If this byte is a match, progress to the next token byte.
self . pos + = 1 ;
// NORA: If we've reached the end of the token,
// that's a successful match.
if self . pos = = self . token . len ( ) {
// NORA: Write the whole suffix into the output buffer.
for suffix_byte in self . suffix {
buffer . push ( * suffix_byte ) ;
}
// NORA: And reset to zero, so we can look for a new match.
self . pos = 0 ;
}
} else {
// NORA: If the current input byte isn't a match for the current
// token byte, we have failed to match the token;
// reset to the beginning.
// This prevents e.g. "oat meal" from matching "oatmeal".
self . pos = 0 ;
}
}
output . write_all ( & buffer )
}
}