1use std::io::Error;
2use std::io::Read;
3use std::io::Write;
4
5use crate::checksum_reader::ChecksumReader;
6use crate::checksum_writer::ChecksumWriter;
7use crate::codec::Codec;
8use crate::fixed_size::FixedSize;
9
10#[derive(Debug)]
12#[derive(Clone)]
13#[derive(PartialEq, Eq)]
14pub struct WithChecksum<T> {
15 pub(crate) data: T,
16}
17
18impl<T> WithChecksum<T> {
19 pub fn new(data: T) -> Self {
20 Self { data }
21 }
22
23 pub fn into_inner(self) -> T {
24 self.data
25 }
26}
27
28impl<T: FixedSize> FixedSize for WithChecksum<T> {
29 fn encoded_size() -> usize {
30 T::encoded_size() + 8
31 }
32}
33
34impl<T> Codec for WithChecksum<T>
35where T: Codec
36{
37 fn encode<W: Write>(&self, mut w: W) -> Result<usize, Error> {
38 let mut n = 0;
39 let mut cw = ChecksumWriter::new(&mut w);
40
41 n += self.data.encode(&mut cw)?;
42 n += cw.write_checksum()?;
43
44 Ok(n)
45 }
46
47 fn decode<R: Read>(r: R) -> Result<Self, Error> {
48 let mut cr = ChecksumReader::new(r);
49
50 let data = T::decode(&mut cr)?;
51 cr.verify_checksum(|| "WithChecksum::decode()")?;
52
53 let meta = Self { data };
54
55 Ok(meta)
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use crate::codec::Codec;
62 use crate::testing::test_codec;
63 use crate::with_checksum::WithChecksum;
64
65 #[test]
66 fn test_with_checksum_codec() -> anyhow::Result<()> {
67 let wc = WithChecksum::<u64>::new(5);
68 let mut b = Vec::new();
69 let n = wc.encode(&mut b)?;
70 assert_eq!(n, b.len());
71
72 assert_eq!(
73 vec![
74 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 21, 72, 43, 230, ],
77 b
78 );
79
80 test_codec(b.as_slice(), &wc)?;
81
82 Ok(())
83 }
84}