aws_smithy_eventstream/buf/
crc.rs
1use bytes::buf::UninitSlice;
9use bytes::{Buf, BufMut};
10use crc32fast::Hasher;
11
12pub(crate) struct CrcBuf<'a, B>
15where
16 B: Buf,
17{
18 buffer: &'a mut B,
19 crc: Hasher,
20}
21
22impl<'a, B> CrcBuf<'a, B>
23where
24 B: Buf,
25{
26 pub(crate) fn new(buffer: &'a mut B) -> Self {
28 CrcBuf {
29 buffer,
30 crc: Hasher::new(),
31 }
32 }
33
34 pub(crate) fn into_crc(self) -> u32 {
36 self.crc.finalize()
37 }
38}
39
40impl<'a, B> Buf for CrcBuf<'a, B>
41where
42 B: Buf,
43{
44 fn remaining(&self) -> usize {
45 self.buffer.remaining()
46 }
47
48 fn chunk(&self) -> &[u8] {
49 self.buffer.chunk()
50 }
51
52 fn advance(&mut self, cnt: usize) {
53 let chunk = self.buffer.chunk();
54 self.crc.update(&chunk[0..cnt]);
55 self.buffer.advance(cnt);
56 }
57}
58
59#[cfg(test)]
60mod crc_buf_tests {
61 use super::CrcBuf;
62 use bytes::Buf;
63
64 #[test]
65 fn crc_no_data_read() {
66 let mut data: &[u8] = &[];
67 let buf = CrcBuf::new(&mut data);
68 assert_eq!(0, buf.into_crc());
69 }
70
71 #[test]
72 fn crc_data_read() {
73 let mut data: &[u8] = &[0, 0, 0, 5, 0, 10u8];
74 let mut buf = CrcBuf::new(&mut data);
75 assert_eq!(5, buf.get_i32());
76 assert_eq!(0x512E2B93, buf.into_crc());
77
78 let mut data: &[u8] = &[0, 0, 0, 5, 0, 10u8];
79 let mut buf = CrcBuf::new(&mut data);
80 assert_eq!(5, buf.get_i32());
81 assert_eq!(10, buf.get_i16());
82 assert_eq!(0x57DC8A56, buf.into_crc());
83 }
84
85 #[test]
86 fn chunk_called_multiple_times_before_advance() {
87 let mut data: &[u8] = &[0, 0, 0, 5, 0, 10u8];
88 let mut buf = CrcBuf::new(&mut data);
89 for _ in 0..3 {
90 buf.chunk();
91 }
92 buf.advance(4);
93 assert_eq!(10, buf.get_i16());
94 assert_eq!(0x57DC8A56, buf.into_crc());
95 }
96}
97
98pub(crate) struct CrcBufMut<'a> {
102 buffer: &'a mut dyn BufMut,
103 crc: Hasher,
104}
105
106impl<'a> CrcBufMut<'a> {
107 pub(crate) fn new(buffer: &'a mut dyn BufMut) -> Self {
109 CrcBufMut {
110 buffer,
111 crc: Hasher::new(),
112 }
113 }
114
115 pub(crate) fn put_crc(&mut self) {
119 self.put_u32(self.crc.clone().finalize());
120 }
121}
122
123unsafe impl<'a> BufMut for CrcBufMut<'a> {
124 fn remaining_mut(&self) -> usize {
125 self.buffer.remaining_mut()
126 }
127
128 unsafe fn advance_mut(&mut self, cnt: usize) {
129 let written = std::slice::from_raw_parts_mut(self.chunk_mut().as_mut_ptr(), cnt);
133 self.crc.update(written);
134 self.buffer.advance_mut(cnt);
135 }
136
137 fn chunk_mut(&mut self) -> &mut UninitSlice {
138 self.buffer.chunk_mut()
139 }
140}
141
142#[cfg(test)]
143mod crc_buf_mut_tests {
144 use super::CrcBufMut;
145 use bytes::BufMut;
146
147 #[test]
148 fn crc_no_bytes_written() {
149 let mut buffer: Vec<u8> = Vec::new();
150 let mut crc_buf = CrcBufMut::new(&mut buffer);
151 crc_buf.put_crc();
152 crc_buf.put_crc();
153 assert_eq!(vec![0, 0, 0, 0u8, 0x21, 0x44, 0xDF, 0x1C], buffer);
154 }
155
156 #[test]
157 fn crc_bytes_written() {
158 let mut buffer: Vec<u8> = Vec::new();
159 let mut crc_buf = CrcBufMut::new(&mut buffer);
160 crc_buf.put_u32(5);
161 crc_buf.put_crc();
162 assert_eq!(vec![0, 0, 0, 5, 0x51, 0x2E, 0x2B, 0x93], buffer);
163 }
164}