Solution

  1. use std::io::Read;
  2. struct RotDecoder<R: Read> {
  3.     input: R,
  4.     rot: u8,
  5. }
  6. impl<R: Read> Read for RotDecoder<R> {
  7.     fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
  8.         let size = self.input.read(buf)?;
  9.         for b in &mut buf[..size] {
  10.             if b.is_ascii_alphabetic() {
  11.                 let base = if b.is_ascii_uppercase() { 'A' } else { 'a' } as u8;
  12.                 *b = (*b - base + self.rot) % 26 + base;
  13.             }
  14.         }
  15.         Ok(size)
  16.     }
  17. }
  18. fn main() {
  19.     let mut rot =
  20.         RotDecoder { input: "Gb trg gb gur bgure fvqr!".as_bytes(), rot: 13 };
  21.     let mut result = String::new();
  22.     rot.read_to_string(&mut result).unwrap();
  23.     println!("{}", result);
  24. }
  25. #[cfg(test)]
  26. mod test {
  27.     use super::*;
  28.     #[test]
  29.     fn joke() {
  30.         let mut rot =
  31.             RotDecoder { input: "Gb trg gb gur bgure fvqr!".as_bytes(), rot: 13 };
  32.         let mut result = String::new();
  33.         rot.read_to_string(&mut result).unwrap();
  34.         assert_eq!(&result, "To get to the other side!");
  35.     }
  36.     #[test]
  37.     fn binary() {
  38.         let input: Vec<u8> = (0..=255u8).collect();
  39.         let mut rot = RotDecoder::<&[u8]> { input: input.as_ref(), rot: 13 };
  40.         let mut buf = [0u8; 256];
  41.         assert_eq!(rot.read(&mut buf).unwrap(), 256);
  42.         for i in 0..=255 {
  43.             if input[i] != buf[i] {
  44.                 assert!(input[i].is_ascii_alphabetic());
  45.                 assert!(buf[i].is_ascii_alphabetic());
  46.             }
  47.         }
  48.     }
  49. }