protocol/wire/middleware/
rotate_bytes.rs

1//! A fixed-offset based caesar cipher middleware.
2
3use crate::{wire, Error};
4
5use std::num::Wrapping;
6
7/// Middleware that rotates each transmitted byte by a fixed offset.
8///
9/// **NOTE**: This is not really useful in real life.
10#[derive(Copy, Clone, Debug)]
11pub struct RotateBytes {
12    /// The integer offset to rotate by.
13    pub amount: u8,
14}
15
16impl RotateBytes {
17    /// The ROT13 cipher.
18    ///
19    /// [ROT13 on Wikipedia](https://en.wikipedia.org/wiki/ROT13)
20    pub const ROT13: RotateBytes = RotateBytes { amount: 13 };
21}
22
23impl wire::Middleware for RotateBytes {
24    fn encode_data(&mut self, data: Vec<u8>) -> Result<Vec<u8>, Error> {
25        Ok(data.into_iter().map(|b| (Wrapping(b) + Wrapping(self.amount)).0).collect())
26    }
27
28    fn decode_data(&mut self, data: Vec<u8>) -> Result<Vec<u8>, Error> {
29        Ok(data.into_iter().map(|b| (Wrapping(b) - Wrapping(self.amount)).0).collect())
30    }
31}
32
33#[cfg(test)]
34mod test {
35    use super::RotateBytes;
36    use crate::wire::Middleware;
37
38    #[test]
39    fn bytes_encoded_correctly() {
40        assert_eq!(RotateBytes::ROT13.clone().encode_data(vec![0, 1, 2, 3, 4]).unwrap(),
41                   vec![13, 14, 15, 16, 17]);
42    }
43
44    #[test]
45    fn bytes_decoded_correctly() {
46        assert_eq!(RotateBytes::ROT13.clone().decode_data(vec![13, 14, 15, 16, 17]).unwrap(),
47                   vec![0, 1, 2, 3, 4]);
48    }
49
50    #[test]
51    fn bytes_read_back_correctly() {
52        assert_eq!(RotateBytes::ROT13.clone().encode_data(RotateBytes::ROT13.clone().decode_data(vec![2, 4, 8, 32, 254]).unwrap()).unwrap(),
53                   vec![2, 4, 8, 32, 254]);
54    }
55}
56