websocket_base/ws/util/
mask.rs1use rand;
3use std::io::Result as IoResult;
4use std::io::Write;
5
6pub struct Masker<'w> {
9 key: [u8; 4],
10 pos: usize,
11 end: &'w mut dyn Write,
12}
13
14impl<'w> Masker<'w> {
15 pub fn new(key: [u8; 4], endpoint: &'w mut dyn Write) -> Self {
18 Masker {
19 key,
20 pos: 0,
21 end: endpoint,
22 }
23 }
24}
25
26impl<'w> Write for Masker<'w> {
27 fn write(&mut self, data: &[u8]) -> IoResult<usize> {
28 let mut buf = Vec::with_capacity(data.len());
29 for &byte in data.iter() {
30 buf.push(byte ^ self.key[self.pos]);
31 self.pos = (self.pos + 1) % self.key.len();
32 }
33 self.end.write(&buf)
34 }
35
36 fn flush(&mut self) -> IoResult<()> {
37 self.end.flush()
38 }
39}
40
41pub fn gen_mask() -> [u8; 4] {
43 rand::random()
44}
45
46pub fn mask_data(mask: [u8; 4], data: &[u8]) -> Vec<u8> {
48 let mut out = Vec::with_capacity(data.len());
49 let zip_iter = data.iter().zip(mask.iter().cycle());
50 for (&buf_item, &key_item) in zip_iter {
51 out.push(buf_item ^ key_item);
52 }
53 out
54}
55
56#[cfg(all(feature = "nightly", test))]
57mod tests {
58 use super::*;
59 use test;
60
61 #[test]
62 fn test_mask_data() {
63 let key = [1u8, 2u8, 3u8, 4u8];
64 let original = vec![10u8, 11u8, 12u8, 13u8, 14u8, 15u8, 16u8, 17u8];
65 let expected = vec![11u8, 9u8, 15u8, 9u8, 15u8, 13u8, 19u8, 21u8];
66 let obtained = mask_data(key, &original[..]);
67 let reversed = mask_data(key, &obtained[..]);
68
69 assert_eq!(original, reversed);
70 assert_eq!(obtained, expected);
71 }
72
73 #[bench]
74 fn bench_mask_data(b: &mut test::Bencher) {
75 let buffer = b"The quick brown fox jumps over the lazy dog";
76 let key = gen_mask();
77 b.iter(|| {
78 let mut output = mask_data(key, buffer);
79 test::black_box(&mut output);
80 });
81 }
82
83 #[bench]
84 fn bench_gen_mask(b: &mut test::Bencher) {
85 b.iter(|| {
86 let mut key = gen_mask();
87 test::black_box(&mut key);
88 });
89 }
90}