1use crc64::crc64;
8use std::fmt;
9use std::io::{Read, Write};
10
11pub struct CRC64Reader<T> {
29 reader: T,
30 crc64: u64,
31}
32
33impl<T> fmt::Debug for CRC64Reader<T> {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 write!(f, "CRC64Reader {{ .. }}")
36 }
37}
38
39impl<T> CRC64Reader<T>
40where
41 T: Read,
42{
43 pub fn new(reader: T) -> Self {
45 CRC64Reader { crc64: 0, reader }
46 }
47 pub fn checksum(&self) -> u64 {
49 self.crc64
50 }
51}
52
53impl<T> Read for CRC64Reader<T>
54where
55 T: Read,
56{
57 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
58 let bytes_read = self.reader.read(buf)?;
59 self.crc64 = crc64(self.crc64, &buf[..bytes_read]);
60 Ok(bytes_read)
61 }
62}
63
64pub struct CRC64Writer<T> {
82 writer: T,
83 crc64: u64,
84}
85
86impl<T> fmt::Debug for CRC64Writer<T> {
87 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88 write!(f, "CRC64Writer {{ .. }}")
89 }
90}
91
92impl<T> CRC64Writer<T>
93where
94 T: Write,
95{
96 pub fn new(writer: T) -> Self {
98 CRC64Writer { crc64: 0, writer }
99 }
100
101 pub fn checksum(&self) -> u64 {
103 self.crc64
104 }
105}
106
107impl<T> Write for CRC64Writer<T>
108where
109 T: Write,
110{
111 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
112 let bytes_written = self.writer.write(buf)?;
113 self.crc64 = crc64(self.crc64, &buf[..bytes_written]);
114 Ok(bytes_written)
115 }
116
117 fn flush(&mut self) -> std::io::Result<()> {
118 self.writer.flush()
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::{CRC64Reader, CRC64Writer, Read, Write};
125
126 #[test]
127 fn test_crc_new() {
128 let buf = vec![1; 5];
129 let mut slice = buf.as_slice();
130 let crc_reader = CRC64Reader::new(&mut slice);
131 assert_eq!(crc_reader.crc64, 0);
132 assert_eq!(crc_reader.reader, &[1; 5]);
133 assert_eq!(crc_reader.checksum(), 0);
134
135 let mut buf = vec![0; 5];
136 let mut slice = buf.as_mut_slice();
137 let crc_writer = CRC64Writer::new(&mut slice);
138 assert_eq!(crc_writer.crc64, 0);
139 assert_eq!(crc_writer.writer, &[0; 5]);
140 assert_eq!(crc_writer.checksum(), 0);
141 }
142
143 #[test]
144 fn test_crc_read() {
145 let buf = vec![1, 2, 3, 4, 5];
146 let mut read_buf = vec![0; 16];
147
148 let mut slice = buf.as_slice();
149 let mut crc_reader = CRC64Reader::new(&mut slice);
150 crc_reader.read_to_end(&mut read_buf).unwrap();
151 assert_eq!(crc_reader.checksum(), 0xFB04_60DE_0638_3654);
152 assert_eq!(crc_reader.checksum(), crc_reader.crc64);
153 }
154
155 #[test]
156 fn test_crc_write() {
157 let mut buf = vec![0; 16];
158 let write_buf = vec![123; 16];
159
160 let mut slice = buf.as_mut_slice();
161 let mut crc_writer = CRC64Writer::new(&mut slice);
162 crc_writer.write_all(write_buf.as_slice()).unwrap();
163 crc_writer.flush().unwrap();
164 assert_eq!(crc_writer.checksum(), 0x29D5_3572_1632_6566);
165 assert_eq!(crc_writer.checksum(), crc_writer.crc64);
166 }
167}