1const START_STATE: u16 = 0xE9CF;
2
3pub(crate) fn whiten(data: &mut [u8]) {
4 let mut state = START_STATE;
5
6 for d in data.iter_mut() {
7 let b;
8 (b, state) = lfsr_byte(state);
9 *d ^= b;
10 }
11}
12
13fn lfsr_byte(mut state: u16) -> (u8, u16) {
15 let mut out = 0;
16 for i in (0..8).rev() {
17 out |= u8::try_from(state & 1).unwrap() << i;
18 state = lfsr(state);
19 }
20
21 (out, state)
22}
23
24fn lfsr(mut state: u16) -> u16 {
26 let lsb = state & 1;
27 state >>= 1;
28 if lsb > 0 {
29 state ^= 0xB400; }
31
32 state
33}
34
35#[cfg(test)]
36mod tests {
37 use super::*;
38
39 #[test]
40 fn basic() {
41 let mut data = [0; 64];
42 data[0..57]
43 .clone_from_slice(&b"Hello world! The quick brown fox jumped over the lazy dog"[..]);
44 let orig = data;
45
46 whiten(&mut data);
47 assert_ne!(orig, data);
48
49 whiten(&mut data);
50 assert_eq!(orig, data);
51 }
52
53 #[test]
54 fn test_lfsr() {
55 let start = 0xACE1;
56 let end_expected = 0xE270;
57
58 let state = lfsr(start);
59
60 assert_eq!(end_expected, state);
61 }
62
63 #[test]
64 fn test_lfsr_byte() {
65 let start = 0xE9CF;
66 let (out, state) = lfsr_byte(start);
67 assert_eq!(0xF3, out);
68 assert_eq!(0xE3B1, state);
69 }
70
71 #[test]
72 fn test_doc_example() {
73 let start = 0xE9CF;
74 let expected_out = [
75 0xF3, 0x8D, 0xD0, 0x6E, 0x1F, 0x65, 0x75, 0x75, 0xA5, 0xBA, 0xA9, 0xD0, 0x7A, 0x1D,
76 0x1, 0x21,
77 ];
78
79 let mut actual_out = [0; 16];
80 let mut state = start;
81 for a in &mut actual_out {
82 let (out, ns) = lfsr_byte(state);
83 state = ns;
84 *a = out;
85 }
86
87 assert_eq!(expected_out, actual_out);
88 }
89
90 #[test]
91 fn test_doc_example_through_whitener() {
92 let expected_out = [
93 0xF3, 0x8D, 0xD0, 0x6E, 0x1F, 0x65, 0x75, 0x75, 0xA5, 0xBA, 0xA9, 0xD0, 0x7A, 0x1D,
94 0x1, 0x21,
95 ];
96
97 let mut actual_out = [0; 16];
98 whiten(&mut actual_out);
99
100 assert_eq!(expected_out, actual_out);
101 }
102}