1use std::io::Error;
2use std::io::Read;
3use std::io::Write;
4use std::marker::PhantomData;
5
6use crate::codec::Decode;
7use crate::codec::Encode;
8use crate::config::CodeqConfig;
9use crate::fixed_size::FixedSize;
10
11#[cfg_attr(not(feature = "crc32fast"), doc = "```ignore")]
21#[cfg_attr(feature = "crc32fast", doc = "```rust")]
22#[derive(Debug)]
43#[derive(Clone)]
44#[derive(PartialEq, Eq)]
45pub struct WithChecksum<C, T>
46where C: CodeqConfig
47{
48 pub(crate) data: T,
49 _p: PhantomData<C>,
50}
51
52impl<C, T> WithChecksum<C, T>
53where C: CodeqConfig
54{
55 pub fn new(data: T) -> Self {
57 Self {
58 data,
59 _p: Default::default(),
60 }
61 }
62
63 pub fn into_inner(self) -> T {
65 self.data
66 }
67}
68
69impl<C, T> FixedSize for WithChecksum<C, T>
70where
71 C: CodeqConfig,
72 T: FixedSize,
73{
74 fn encoded_size() -> usize {
75 T::encoded_size() + 8
76 }
77}
78
79impl<C, T> Encode for WithChecksum<C, T>
80where
81 C: CodeqConfig,
82 T: Encode,
83{
84 fn encode<W: Write>(&self, mut w: W) -> Result<usize, Error> {
85 let mut n = 0;
86 let mut cw = C::new_writer(&mut w);
87
88 n += self.data.encode(&mut cw)?;
89 n += cw.write_checksum()?;
90
91 Ok(n)
92 }
93}
94
95impl<C, T> Decode for WithChecksum<C, T>
96where
97 C: CodeqConfig,
98 T: Decode,
99{
100 fn decode<R: Read>(r: R) -> Result<Self, Error> {
101 let mut cr = C::new_reader(r);
102
103 let data = T::decode(&mut cr)?;
104 cr.verify_checksum(|| "WithChecksum::decode()")?;
105
106 let meta = Self {
107 data,
108 _p: Default::default(),
109 };
110
111 Ok(meta)
112 }
113}
114
115#[cfg(feature = "crc32fast")]
116#[cfg(test)]
117mod tests_crc32fast {
118 use crate::codec::Encode;
119 use crate::config::CodeqConfig;
120 use crate::config::Crc32fast;
121 use crate::testing::test_codec;
122
123 #[test]
124 fn test_with_checksum_codec() -> anyhow::Result<()> {
125 let wc = Crc32fast::wrap(5u64);
126 let mut b = Vec::new();
127 let n = wc.encode(&mut b)?;
128 assert_eq!(n, b.len());
129
130 assert_eq!(
131 vec![
132 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 21, 72, 43, 230, ],
135 b
136 );
137
138 test_codec(b.as_slice(), &wc)?;
139
140 Ok(())
141 }
142}