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