diff --git a/src/lib.rs b/src/lib.rs index 6e4404c..3824336 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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) } }