1use crate::{
22 util::at_least, varint::UInt, EncodeSize, Error, FixedSize, RangeCfg, Read, ReadExt, Write,
23};
24use bytes::{Buf, BufMut};
25
26macro_rules! impl_numeric {
28 ($type:ty, $read_method:ident, $write_method:ident) => {
29 impl Write for $type {
30 #[inline]
31 fn write(&self, buf: &mut impl BufMut) {
32 buf.$write_method(*self);
33 }
34 }
35
36 impl Read for $type {
37 type Cfg = ();
38 #[inline]
39 fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, Error> {
40 at_least(buf, std::mem::size_of::<$type>())?;
41 Ok(buf.$read_method())
42 }
43 }
44
45 impl FixedSize for $type {
46 const SIZE: usize = std::mem::size_of::<$type>();
47 }
48 };
49}
50
51impl_numeric!(u8, get_u8, put_u8);
52impl_numeric!(u16, get_u16, put_u16);
53impl_numeric!(u32, get_u32, put_u32);
54impl_numeric!(u64, get_u64, put_u64);
55impl_numeric!(u128, get_u128, put_u128);
56impl_numeric!(i8, get_i8, put_i8);
57impl_numeric!(i16, get_i16, put_i16);
58impl_numeric!(i32, get_i32, put_i32);
59impl_numeric!(i64, get_i64, put_i64);
60impl_numeric!(i128, get_i128, put_i128);
61impl_numeric!(f32, get_f32, put_f32);
62impl_numeric!(f64, get_f64, put_f64);
63
64impl Write for usize {
66 #[inline]
67 fn write(&self, buf: &mut impl BufMut) {
68 let self_as_u32 = u32::try_from(*self).expect("write: usize value is larger than u32");
69 UInt(self_as_u32).write(buf);
70 }
71}
72
73impl Read for usize {
74 type Cfg = RangeCfg;
75
76 #[inline]
77 fn read_cfg(buf: &mut impl Buf, range: &Self::Cfg) -> Result<Self, Error> {
78 let self_as_u32: u32 = UInt::read(buf)?.into();
79 let result = usize::try_from(self_as_u32).map_err(|_| Error::InvalidUsize)?;
80 if !range.contains(&result) {
81 return Err(Error::InvalidLength(result));
82 }
83 Ok(result)
84 }
85}
86
87impl EncodeSize for usize {
88 #[inline]
89 fn encode_size(&self) -> usize {
90 let self_as_u32 =
91 u32::try_from(*self).expect("encode_size: usize value is larger than u32");
92 UInt(self_as_u32).encode_size()
93 }
94}
95
96impl Write for bool {
98 #[inline]
99 fn write(&self, buf: &mut impl BufMut) {
100 buf.put_u8(if *self { 1 } else { 0 });
101 }
102}
103
104impl Read for bool {
105 type Cfg = ();
106 #[inline]
107 fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, Error> {
108 match u8::read(buf)? {
109 0 => Ok(false),
110 1 => Ok(true),
111 _ => Err(Error::InvalidBool),
112 }
113 }
114}
115
116impl FixedSize for bool {
117 const SIZE: usize = 1;
118}
119
120impl<const N: usize> Write for [u8; N] {
122 #[inline]
123 fn write(&self, buf: &mut impl BufMut) {
124 buf.put(&self[..]);
125 }
126}
127
128impl<const N: usize> Read for [u8; N] {
129 type Cfg = ();
130 #[inline]
131 fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, Error> {
132 at_least(buf, N)?;
133 let mut dst = [0; N];
134 buf.copy_to_slice(&mut dst);
135 Ok(dst)
136 }
137}
138
139impl<const N: usize> FixedSize for [u8; N] {
140 const SIZE: usize = N;
141}
142
143impl<T: Write> Write for Option<T> {
145 #[inline]
146 fn write(&self, buf: &mut impl BufMut) {
147 self.is_some().write(buf);
148 if let Some(inner) = self {
149 inner.write(buf);
150 }
151 }
152}
153
154impl<T: EncodeSize> EncodeSize for Option<T> {
155 #[inline]
156 fn encode_size(&self) -> usize {
157 match self {
158 Some(inner) => 1 + inner.encode_size(),
159 None => 1,
160 }
161 }
162}
163
164impl<T: Read> Read for Option<T> {
165 type Cfg = T::Cfg;
166
167 #[inline]
168 fn read_cfg(buf: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
169 if bool::read(buf)? {
170 Ok(Some(T::read_cfg(buf, cfg)?))
171 } else {
172 Ok(None)
173 }
174 }
175}
176
177#[cfg(test)]
178mod tests {
179 use super::*;
180 use crate::{Decode, DecodeExt, Encode, EncodeFixed};
181 use bytes::{Bytes, BytesMut};
182 use paste::paste;
183
184 macro_rules! impl_num_test {
186 ($type:ty, $size:expr) => {
187 paste! {
188 #[test]
189 fn [<test_ $type>]() {
190 let expected_len = std::mem::size_of::<$type>();
191 let values: [$type; 5] =
192 [0 as $type, 1 as $type, 42 as $type, <$type>::MAX, <$type>::MIN];
193 for value in values.iter() {
194 let encoded = value.encode();
195 assert_eq!(encoded.len(), expected_len);
196 let decoded = <$type>::decode(encoded).unwrap();
197 assert_eq!(*value, decoded);
198 assert_eq!(value.encode_size(), expected_len);
199
200 let fixed: [u8; $size] = value.encode_fixed();
201 assert_eq!(fixed.len(), expected_len);
202 let decoded = <$type>::decode(Bytes::copy_from_slice(&fixed)).unwrap();
203 assert_eq!(*value, decoded);
204 }
205 }
206 }
207 };
208 }
209 impl_num_test!(u8, 1);
210 impl_num_test!(u16, 2);
211 impl_num_test!(u32, 4);
212 impl_num_test!(u64, 8);
213 impl_num_test!(u128, 16);
214 impl_num_test!(i8, 1);
215 impl_num_test!(i16, 2);
216 impl_num_test!(i32, 4);
217 impl_num_test!(i64, 8);
218 impl_num_test!(i128, 16);
219 impl_num_test!(f32, 4);
220 impl_num_test!(f64, 8);
221
222 #[test]
223 fn test_endianness() {
224 let encoded = 0x0102u16.encode();
226 assert_eq!(encoded, Bytes::from_static(&[0x01, 0x02]));
227
228 let encoded = 0x01020304u32.encode();
230 assert_eq!(encoded, Bytes::from_static(&[0x01, 0x02, 0x03, 0x04]));
231
232 let encoded = 1.0f32.encode();
234 assert_eq!(encoded, Bytes::from_static(&[0x3F, 0x80, 0x00, 0x00])); }
236
237 #[test]
238 fn test_bool() {
239 let values = [true, false];
240 for value in values.iter() {
241 let encoded = value.encode();
242 assert_eq!(encoded.len(), 1);
243 let decoded = bool::decode(encoded).unwrap();
244 assert_eq!(*value, decoded);
245 assert_eq!(value.encode_size(), 1);
246 }
247 }
248
249 #[test]
250 fn test_usize() {
251 let values = [0usize, 1, 42, u32::MAX as usize];
252 for value in values.iter() {
253 let encoded = value.encode();
254 assert_eq!(value.encode_size(), UInt(*value as u32).encode_size());
255 let decoded = usize::decode_cfg(encoded, &(..).into()).unwrap();
256 assert_eq!(*value, decoded);
257 }
258 }
259
260 #[cfg(target_pointer_width = "64")]
261 #[test]
262 #[should_panic(expected = "encode_size: usize value is larger than u32")]
263 fn test_usize_encode_panic() {
264 let value: usize = usize::MAX;
265 let _ = value.encode();
266 }
267
268 #[test]
269 #[should_panic(expected = "write: usize value is larger than u32")]
270 fn test_usize_write_panic() {
271 let mut buf = &mut BytesMut::new();
272 let value: usize = usize::MAX;
273 value.write(&mut buf);
274 }
275
276 #[test]
277 fn test_array() {
278 let values = [1u8, 2, 3];
279 let encoded = values.encode();
280 let decoded = <[u8; 3]>::decode(encoded).unwrap();
281 assert_eq!(values, decoded);
282 }
283
284 #[test]
285 fn test_option() {
286 let option_values = [Some(42u32), None];
287 for value in option_values {
288 let encoded = value.encode();
289 let decoded = Option::<u32>::decode(encoded).unwrap();
290 assert_eq!(value, decoded);
291 }
292 }
293
294 #[test]
295 fn test_option_length() {
296 let some = Some(42u32);
297 assert_eq!(some.encode_size(), 1 + 4);
298 assert_eq!(some.encode().len(), 1 + 4);
299 let none: Option<u32> = None;
300 assert_eq!(none.encode_size(), 1);
301 assert_eq!(none.encode().len(), 1);
302 }
303}