1use crate::format::{BOOL_FALSE, BOOL_TRUE, OPTION_NONE, OPTION_SOME, RESULT_ERR, RESULT_OK};
4use crate::{CanonicalDecode, CanonicalEncode, CodecError, DecodeSource, EncodeSink};
5
6macro_rules! impl_int {
7 ($ty:ty) => {
8 impl CanonicalEncode for $ty {
9 fn encode<W: EncodeSink + ?Sized>(&self, writer: &mut W) -> Result<(), CodecError> {
10 writer.write_all(&self.to_le_bytes())
11 }
12 }
13
14 impl CanonicalDecode for $ty {
15 fn decode<R: DecodeSource + ?Sized>(reader: &mut R) -> Result<Self, CodecError> {
16 let mut bytes = [0u8; core::mem::size_of::<$ty>()];
17 reader.read_exact(&mut bytes)?;
18 Ok(<$ty>::from_le_bytes(bytes))
19 }
20 }
21 };
22}
23
24impl_int!(u16);
25impl_int!(i16);
26impl_int!(u32);
27impl_int!(i32);
28impl_int!(u64);
29impl_int!(i64);
30impl_int!(u128);
31impl_int!(i128);
32
33impl CanonicalEncode for u8 {
34 fn encode<W: EncodeSink + ?Sized>(&self, writer: &mut W) -> Result<(), CodecError> {
35 writer.write_all(&[*self])
36 }
37}
38
39impl CanonicalDecode for u8 {
40 fn decode<R: DecodeSource + ?Sized>(reader: &mut R) -> Result<Self, CodecError> {
41 let mut byte = [0u8; 1];
42 reader.read_exact(&mut byte)?;
43 Ok(byte[0])
44 }
45}
46
47impl CanonicalEncode for i8 {
48 fn encode<W: EncodeSink + ?Sized>(&self, writer: &mut W) -> Result<(), CodecError> {
49 writer.write_all(&self.to_le_bytes())
50 }
51}
52
53impl CanonicalDecode for i8 {
54 fn decode<R: DecodeSource + ?Sized>(reader: &mut R) -> Result<Self, CodecError> {
55 let byte = u8::decode(reader)?;
56 Ok(Self::from_le_bytes([byte]))
57 }
58}
59
60impl CanonicalEncode for bool {
61 fn encode<W: EncodeSink + ?Sized>(&self, writer: &mut W) -> Result<(), CodecError> {
62 writer.write_all(&[if *self { BOOL_TRUE } else { BOOL_FALSE }])
63 }
64}
65
66impl CanonicalDecode for bool {
67 fn decode<R: DecodeSource + ?Sized>(reader: &mut R) -> Result<Self, CodecError> {
68 match u8::decode(reader)? {
69 BOOL_FALSE => Ok(false),
70 BOOL_TRUE => Ok(true),
71 _ => Err(CodecError::invalid_value(
72 "invalid bool byte: expected 0x00 or 0x01",
73 )),
74 }
75 }
76}
77
78impl CanonicalEncode for str {
79 fn encode<W: EncodeSink + ?Sized>(&self, writer: &mut W) -> Result<(), CodecError> {
80 let bytes = self.as_bytes();
81 let len = u32::try_from(bytes.len())
82 .map_err(|_| CodecError::length_overflow("string length exceeds u32::MAX bytes"))?;
83 len.encode(writer)?;
84 writer.write_all(bytes)
85 }
86}
87
88#[cfg(feature = "alloc")]
89impl CanonicalEncode for alloc::string::String {
90 fn encode<W: EncodeSink + ?Sized>(&self, writer: &mut W) -> Result<(), CodecError> {
91 self.as_str().encode(writer)
92 }
93}
94
95#[cfg(feature = "alloc")]
96impl CanonicalDecode for alloc::string::String {
97 fn decode<R: DecodeSource + ?Sized>(reader: &mut R) -> Result<Self, CodecError> {
98 let bytes = read_len_prefixed_bytes(reader, "string")?;
99 Self::from_utf8(bytes)
100 .map_err(|_| CodecError::invalid_value("invalid UTF-8 string payload"))
101 }
102}
103
104#[cfg(feature = "alloc")]
105impl<T: CanonicalEncode> CanonicalEncode for alloc::vec::Vec<T> {
106 fn encode<W: EncodeSink + ?Sized>(&self, writer: &mut W) -> Result<(), CodecError> {
107 let len = u32::try_from(self.len())
108 .map_err(|_| CodecError::length_overflow("vector length exceeds u32::MAX items"))?;
109 len.encode(writer)?;
110 for item in self {
111 item.encode(writer)?;
112 }
113 Ok(())
114 }
115}
116
117#[cfg(feature = "alloc")]
118impl<T: CanonicalDecode> CanonicalDecode for alloc::vec::Vec<T> {
119 fn decode<R: DecodeSource + ?Sized>(reader: &mut R) -> Result<Self, CodecError> {
120 let len = u32::decode(reader)?;
121 let len = usize::try_from(len)
122 .map_err(|_| CodecError::length_overflow("vector length does not fit usize"))?;
123 let mut items = alloc::vec::Vec::new();
124 for _ in 0..len {
125 items.push(T::decode(reader)?);
126 }
127 Ok(items)
128 }
129}
130
131#[cfg(feature = "alloc")]
132fn read_len_prefixed_bytes<R: DecodeSource + ?Sized>(
133 reader: &mut R,
134 context: &'static str,
135) -> Result<alloc::vec::Vec<u8>, CodecError> {
136 const CHUNK_SIZE: usize = 8 * 1024;
137
138 let len = u32::decode(reader)?;
139 let len = usize::try_from(len)
140 .map_err(|_| CodecError::length_overflow("byte length does not fit usize"))?;
141
142 if let Some(remaining) = reader.remaining_len() {
143 if len > remaining {
144 return Err(CodecError::unexpected_eof());
145 }
146 }
147
148 let mut bytes = alloc::vec::Vec::new();
149 let mut remaining = len;
150 while remaining != 0 {
151 let chunk_len = remaining.min(CHUNK_SIZE);
152 bytes.try_reserve_exact(chunk_len).map_err(|_| {
153 CodecError::length_overflow(match context {
154 "string" => "string length exceeds available memory",
155 _ => "byte length exceeds available memory",
156 })
157 })?;
158
159 let start = bytes.len();
160 bytes.resize(start + chunk_len, 0);
161 reader.read_exact(&mut bytes[start..])?;
162 remaining -= chunk_len;
163 }
164
165 Ok(bytes)
166}
167
168impl<T: CanonicalEncode> CanonicalEncode for Option<T> {
169 fn encode<W: EncodeSink + ?Sized>(&self, writer: &mut W) -> Result<(), CodecError> {
170 match self {
171 None => OPTION_NONE.encode(writer),
172 Some(value) => {
173 OPTION_SOME.encode(writer)?;
174 value.encode(writer)
175 }
176 }
177 }
178}
179
180impl<T: CanonicalDecode> CanonicalDecode for Option<T> {
181 fn decode<R: DecodeSource + ?Sized>(reader: &mut R) -> Result<Self, CodecError> {
182 match u8::decode(reader)? {
183 OPTION_NONE => Ok(None),
184 OPTION_SOME => T::decode(reader).map(Some),
185 _ => Err(CodecError::invalid_value(
186 "invalid Option tag: expected 0x00 for None or 0x01 for Some",
187 )),
188 }
189 }
190}
191
192impl<T: CanonicalEncode, E: CanonicalEncode> CanonicalEncode for Result<T, E> {
193 fn encode<W: EncodeSink + ?Sized>(&self, writer: &mut W) -> Result<(), CodecError> {
194 match self {
195 Ok(value) => {
196 RESULT_OK.encode(writer)?;
197 value.encode(writer)
198 }
199 Err(error) => {
200 RESULT_ERR.encode(writer)?;
201 error.encode(writer)
202 }
203 }
204 }
205}
206
207impl<T: CanonicalDecode, E: CanonicalDecode> CanonicalDecode for Result<T, E> {
208 fn decode<R: DecodeSource + ?Sized>(reader: &mut R) -> Result<Self, CodecError> {
209 match u8::decode(reader)? {
210 RESULT_OK => T::decode(reader).map(Ok),
211 RESULT_ERR => E::decode(reader).map(Err),
212 _ => Err(CodecError::invalid_value(
213 "invalid Result tag: expected 0x00 for Ok or 0x01 for Err",
214 )),
215 }
216 }
217}
218
219impl<T: CanonicalEncode, const N: usize> CanonicalEncode for [T; N] {
220 fn encode<W: EncodeSink + ?Sized>(&self, writer: &mut W) -> Result<(), CodecError> {
221 for item in self {
222 item.encode(writer)?;
223 }
224 Ok(())
225 }
226}
227
228#[cfg(feature = "alloc")]
229impl<T: CanonicalDecode, const N: usize> CanonicalDecode for [T; N] {
230 fn decode<R: DecodeSource + ?Sized>(reader: &mut R) -> Result<Self, CodecError> {
231 let mut items = alloc::vec::Vec::with_capacity(N);
232 for _ in 0..N {
233 items.push(T::decode(reader)?);
234 }
235 match items.try_into() {
236 Ok(array) => Ok(array),
237 Err(_) => Err(CodecError::invalid_value("decoded array length mismatch")),
238 }
239 }
240}
241
242#[cfg(not(feature = "alloc"))]
243impl<const N: usize> CanonicalDecode for [u8; N] {
244 fn decode<R: DecodeSource + ?Sized>(reader: &mut R) -> Result<Self, CodecError> {
245 let mut bytes = [0u8; N];
246 reader.read_exact(&mut bytes)?;
247 Ok(bytes)
248 }
249}
250
251macro_rules! impl_tuple {
252 ($($name:ident),+) => {
253 impl<$($name: CanonicalEncode),+> CanonicalEncode for ($($name,)+) {
254 #[allow(non_snake_case)]
255 fn encode<W: EncodeSink + ?Sized>(&self, writer: &mut W) -> Result<(), CodecError> {
256 let ($($name,)+) = self;
257 $($name.encode(writer)?;)+
258 Ok(())
259 }
260 }
261
262 impl<$($name: CanonicalDecode),+> CanonicalDecode for ($($name,)+) {
263 fn decode<R: DecodeSource + ?Sized>(reader: &mut R) -> Result<Self, CodecError> {
264 Ok(($($name::decode(reader)?,)+))
265 }
266 }
267 };
268}
269
270impl_tuple!(A);
271impl_tuple!(A, B);
272impl_tuple!(A, B, C);
273impl_tuple!(A, B, C, D);