use std::io::Write; /// The parser/transformator. Given a `token` and a `suffix`, adds the `suffix` /// after the `token` to any byte buffer given to [`Parser::process`]. /// /// For example, with a `Parser::new(b"foo", b"bar"), calling /// `parser.process(b"is foo a bar?", &mut writer)` will result in /// `"is foobar a bar?"` being written to `writer`. // // NOTE: Feel free to modify this struct as needed. pub struct Parser { token: &'static [u8], suffix: &'static [u8], } impl Parser { /// Create a new `Parser` which will append `suffix` after `token` whenever /// it appears in input passed to `process`. // // NOTE: This function signature should stay the same. pub fn new(token: &'static [u8], suffix: &'static [u8]) -> Self { Self { token, suffix } } /// Write the bytes given in `input` to `output`, plus the bytes in `suffix` /// immediately after `token`, including across call boundaries. /// /// # Examples /// /// If the token is present in the input, the writer gets the input plus /// the suffix right after the token. For instance, here, /// `does this foo go bar?` is transformed into /// `does this foobar go bar?`. /// /// ```rust /// # use code_challenge::Parser; /// let mut parser = Parser::new(b"foo", b"bar"); /// let mut buffer = Vec::new(); /// parser.process(b"does this foo go bar?", &mut buffer).unwrap(); /// assert_eq!(b"does this foobar go bar?", buffer.as_slice()); /// ``` /// /// This works even if the token is split across multiple calls to the /// `process` method on the same instance of `Parser`. /// For instance, this is exactly the same as the previous example, /// but splits the input across multiple calls to `parser`. /// /// ```rust /// # use code_challenge::Parser; /// let mut parser = Parser::new(b"foo", b"bar"); /// let mut buffer = Vec::new(); /// parser.process(b"does this f", &mut buffer).unwrap(); /// parser.process(b"oo go bar?", &mut buffer).unwrap(); /// assert_eq!(b"does this foobar go bar?", buffer.as_slice()); /// ``` // // 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) } } #[test] fn test_output_unmodified() { let mut parser = Parser::new(b"lalala", b""); let mut buffer = Vec::new(); parser .process(b"does not contain the token", &mut buffer) .expect("couldn't write to buffer"); assert_eq!( "does not contain the token", String::from_utf8_lossy(&buffer) ) } #[test] fn test_output_onetoken() { let mut parser = Parser::new(b"token", b"xxx"); let mut buffer = Vec::new(); parser .process(b"does contain the token", &mut buffer) .expect("couldn't write to buffer"); assert_eq!( "does contain the tokenxxx", String::from_utf8_lossy(&buffer) ) } #[test] fn test_output_onetoken_multi() { let mut parser = Parser::new(b"token", b"xxx"); let mut buffer = Vec::new(); parser .process(b"does contain ", &mut buffer) .expect("couldn't write to buffer"); parser .process(b"the tok", &mut buffer) .expect("couldn't write to buffer"); parser .process(b"en", &mut buffer) .expect("couldn't write to buffer"); assert_eq!( "does contain the tokenxxx", String::from_utf8_lossy(&buffer) ) } #[test] fn test_output_splittoken() { let mut parser = Parser::new(b"token", b"xxx"); let mut buffer = Vec::new(); parser .process(b"doesn't contain the tok en", &mut buffer) .expect("couldn't write to buffer"); assert_eq!( "doesn't contain the tok en", String::from_utf8_lossy(&buffer) ) }