Skip to main content

messagepack_core/encode/
int.rs

1//! Integer encoders and size‑minimising helpers.
2
3use num_traits::ToPrimitive;
4
5use super::{Encode, Error, Result};
6use crate::{formats::Format, io::IoWrite};
7
8impl<W> Encode<W> for u8
9where
10    W: IoWrite,
11{
12    fn encode(&self, writer: &mut W) -> Result<usize, W::Error> {
13        match self {
14            0x00..=0x7f => {
15                writer.write(&Format::PositiveFixInt(*self).as_slice())?;
16
17                Ok(1)
18            }
19            _ => {
20                writer.write(&Format::Uint8.as_slice())?;
21                writer.write(&self.to_be_bytes())?;
22                Ok(2)
23            }
24        }
25    }
26}
27
28impl<W> Encode<W> for u128
29where
30    W: IoWrite,
31{
32    fn encode(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
33        match u64::try_from(*self) {
34            Ok(u64_uint) => u64_uint.encode(writer),
35            Err(_) => Err(Error::InvalidFormat),
36        }
37    }
38}
39
40impl<W> Encode<W> for usize
41where
42    W: IoWrite,
43{
44    fn encode(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
45        match u64::try_from(*self) {
46            Ok(u64_uint) => u64_uint.encode(writer),
47            Err(_) => Err(Error::InvalidFormat),
48        }
49    }
50}
51
52impl<W> Encode<W> for i8
53where
54    W: IoWrite,
55{
56    fn encode(&self, writer: &mut W) -> Result<usize, W::Error> {
57        match self {
58            -32..=-1 => {
59                writer.write(&Format::NegativeFixInt(*self).as_slice())?;
60                Ok(1)
61            }
62            _ => {
63                writer.write(&Format::Int8.as_slice())?;
64                writer.write(&self.to_be_bytes())?;
65
66                Ok(2)
67            }
68        }
69    }
70}
71
72impl<W> Encode<W> for isize
73where
74    W: IoWrite,
75{
76    fn encode(&self, writer: &mut W) -> Result<usize, W::Error> {
77        match i64::try_from(*self) {
78            Ok(i64_int) => i64_int.encode(writer),
79            Err(_) => Err(Error::InvalidFormat),
80        }
81    }
82}
83
84impl<W> Encode<W> for i128
85where
86    W: IoWrite,
87{
88    fn encode(&self, writer: &mut W) -> Result<usize, W::Error> {
89        match i64::try_from(*self) {
90            Ok(i64_int) => i64_int.encode(writer),
91            Err(_) => Err(Error::InvalidFormat),
92        }
93    }
94}
95
96macro_rules! impl_encode_int {
97    ($ty:ty,  $format:expr, $size:expr) => {
98        impl<W> Encode<W> for $ty
99        where
100            W: IoWrite,
101        {
102            fn encode(&self, writer: &mut W) -> Result<usize, W::Error> {
103                writer.write(&$format.as_slice())?;
104                writer.write(&self.to_be_bytes())?;
105                Ok($size)
106            }
107        }
108    };
109}
110impl_encode_int!(u16, Format::Uint16, 3);
111impl_encode_int!(u32, Format::Uint32, 5);
112impl_encode_int!(u64, Format::Uint64, 9);
113impl_encode_int!(i16, Format::Int16, 3);
114impl_encode_int!(i32, Format::Int32, 5);
115impl_encode_int!(i64, Format::Int64, 9);
116
117macro_rules! impl_nonzero_int {
118    ($ty:ty) => {
119        impl<W> Encode<W> for $ty
120        where
121            W: IoWrite,
122        {
123            fn encode(&self, writer: &mut W) -> Result<usize, W::Error> {
124                self.get().encode(writer)
125            }
126        }
127    };
128}
129impl_nonzero_int!(core::num::NonZeroU8);
130impl_nonzero_int!(core::num::NonZeroU16);
131impl_nonzero_int!(core::num::NonZeroU32);
132impl_nonzero_int!(core::num::NonZeroU64);
133impl_nonzero_int!(core::num::NonZeroUsize);
134impl_nonzero_int!(core::num::NonZeroI8);
135impl_nonzero_int!(core::num::NonZeroI16);
136impl_nonzero_int!(core::num::NonZeroI32);
137impl_nonzero_int!(core::num::NonZeroI64);
138impl_nonzero_int!(core::num::NonZeroIsize);
139
140macro_rules! impl_atomic_int {
141    ($ty:ty, $bits:literal) => {
142        #[cfg(target_has_atomic = $bits)]
143        impl<W> Encode<W> for $ty
144        where
145            W: IoWrite,
146        {
147            fn encode(&self, writer: &mut W) -> Result<usize, W::Error> {
148                self.load(core::sync::atomic::Ordering::Relaxed)
149                    .encode(writer)
150            }
151        }
152    };
153}
154impl_atomic_int!(core::sync::atomic::AtomicU8, "8");
155impl_atomic_int!(core::sync::atomic::AtomicU16, "16");
156impl_atomic_int!(core::sync::atomic::AtomicU32, "32");
157impl_atomic_int!(core::sync::atomic::AtomicU64, "64");
158impl_atomic_int!(core::sync::atomic::AtomicUsize, "ptr");
159impl_atomic_int!(core::sync::atomic::AtomicI8, "8");
160impl_atomic_int!(core::sync::atomic::AtomicI16, "16");
161impl_atomic_int!(core::sync::atomic::AtomicI32, "32");
162impl_atomic_int!(core::sync::atomic::AtomicI64, "64");
163impl_atomic_int!(core::sync::atomic::AtomicIsize, "ptr");
164
165/// encode minimum byte size
166#[derive(Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq)]
167pub struct EncodeMinimizeInt<N>(pub N);
168
169impl<W, N> Encode<W> for EncodeMinimizeInt<N>
170where
171    W: IoWrite,
172    N: ToPrimitive,
173{
174    fn encode(&self, writer: &mut W) -> Result<usize, W::Error> {
175        let n = &self.0;
176        if let Some(v) = n.to_u8() {
177            v.encode(writer)
178        } else if let Some(v) = n.to_i8() {
179            v.encode(writer)
180        } else if let Some(v) = n.to_u16() {
181            v.encode(writer)
182        } else if let Some(v) = n.to_i16() {
183            v.encode(writer)
184        } else if let Some(v) = n.to_u32() {
185            v.encode(writer)
186        } else if let Some(v) = n.to_i32() {
187            v.encode(writer)
188        } else if let Some(v) = n.to_u64() {
189            v.encode(writer)
190        } else if let Some(v) = n.to_i64() {
191            v.encode(writer)
192        } else {
193            Err(Error::InvalidFormat)
194        }
195    }
196}
197
198#[cfg(test)]
199mod tests {
200    use super::*;
201    use rstest::rstest;
202
203    #[rstest]
204    #[case(u8::MIN,[0x00])]
205    #[case(0x7f_u8,[0x7f])]
206    #[case(0x80_u8,[Format::Uint8.as_byte(), 0x80])]
207    #[case(u8::MAX,[Format::Uint8.as_byte(), 0xff])]
208    fn encode_uint8<V: Encode<Vec<u8>>, E: AsRef<[u8]> + Sized>(
209        #[case] value: V,
210        #[case] expected: E,
211    ) {
212        let expected = expected.as_ref();
213
214        let mut buf: Vec<u8> = vec![];
215        let n = value.encode(&mut buf).unwrap();
216        assert_eq!(buf, expected);
217        assert_eq!(n, expected.len());
218    }
219
220    #[rstest]
221    #[case(u16::MIN,[Format::Uint16.as_byte(),0x00,0x00])]
222    #[case(0x00ff_u16,[Format::Uint16.as_byte(),0x00,0xff])]
223    #[case(0x01ff_u16, [Format::Uint16.as_byte(), 0x01, 0xff])]
224    #[case(u16::MAX, [Format::Uint16.as_byte(), 0xff, 0xff])]
225    fn encode_uint16<V: Encode<Vec<u8>>, E: AsRef<[u8]>>(#[case] value: V, #[case] expected: E) {
226        let expected = expected.as_ref();
227
228        let mut buf = vec![];
229        let n = value.encode(&mut buf).unwrap();
230        assert_eq!(buf, expected);
231        assert_eq!(n, expected.len());
232    }
233
234    #[rstest]
235    #[case(u32::MIN, [Format::Uint32.as_byte(), 0x00, 0x00,0x00, 0x00])]
236    #[case(0x0000ffff_u32, [Format::Uint32.as_byte(), 0x00, 0x00,0xff, 0xff])]
237    #[case(0x0001ffff_u32, [Format::Uint32.as_byte(), 0x00, 0x01,0xff, 0xff])]
238    #[case(u32::MAX, [Format::Uint32.as_byte(),0xff, 0xff, 0xff,0xff])]
239    fn encode_uint32<V: Encode<Vec<u8>>, E: AsRef<[u8]>>(#[case] value: V, #[case] expected: E) {
240        let expected = expected.as_ref();
241
242        let mut buf = vec![];
243        let n = value.encode(&mut buf).unwrap();
244        assert_eq!(buf, expected);
245        assert_eq!(n, expected.len());
246    }
247
248    #[rstest]
249    #[case(u64::MIN, [Format::Uint64.as_byte(), 0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00])]
250    #[case(u64::MAX, [Format::Uint64.as_byte(), 0xff, 0xff, 0xff,0xff,0xff, 0xff, 0xff,0xff])]
251    fn encode_uint64<V: Encode<Vec<u8>>, E: AsRef<[u8]>>(#[case] value: V, #[case] expected: E) {
252        let expected = expected.as_ref();
253
254        let mut buf = vec![];
255        let n = value.encode(&mut buf).unwrap();
256        assert_eq!(buf, expected);
257        assert_eq!(n, expected.len());
258    }
259
260    #[rstest]
261    #[case(i8::MIN,[Format::Int8.as_byte(),0x80])]
262    #[case(-32_i8,[0xe0])]
263    #[case(-1_i8,[0xff])]
264    #[case(0_i8,[Format::Int8.as_byte(),0x00])]
265    #[case(i8::MAX,[Format::Int8.as_byte(),0x7f])]
266    fn encode_int8<V: Encode<Vec<u8>>, E: AsRef<[u8]> + Sized>(
267        #[case] value: V,
268        #[case] expected: E,
269    ) {
270        let expected = expected.as_ref();
271
272        let mut buf = vec![];
273        let n = value.encode(&mut buf).unwrap();
274        assert_eq!(buf, expected);
275        assert_eq!(n, expected.len());
276    }
277
278    #[rstest]
279    #[case(i16::MIN,[Format::Int16.as_byte(),0x80,0x00])]
280    #[case(-1_i16,[Format::Int16.as_byte(),0xff,0xff])]
281    #[case(0_i16,[Format::Int16.as_byte(),0x00,0x00])]
282    #[case(i16::MAX,[Format::Int16.as_byte(),0x7f,0xff])]
283    fn encode_int16<V: Encode<Vec<u8>>, E: AsRef<[u8]> + Sized>(
284        #[case] value: V,
285        #[case] expected: E,
286    ) {
287        let expected = expected.as_ref();
288
289        let mut buf = vec![];
290        let n = value.encode(&mut buf).unwrap();
291        assert_eq!(buf, expected);
292        assert_eq!(n, expected.len());
293    }
294
295    #[rstest]
296    #[case(i32::MIN,[Format::Int32.as_byte(),0x80,0x00,0x00,0x00])]
297    #[case(-1_i32,[Format::Int32.as_byte(),0xff,0xff,0xff,0xff])]
298    #[case(0_i32,[Format::Int32.as_byte(),0x00,0x00,0x00,0x00])]
299    #[case(i32::MAX,[Format::Int32.as_byte(),0x7f,0xff,0xff,0xff])]
300    fn encode_int32<V: Encode<Vec<u8>>, E: AsRef<[u8]> + Sized>(
301        #[case] value: V,
302        #[case] expected: E,
303    ) {
304        let expected = expected.as_ref();
305
306        let mut buf = vec![];
307        let n = value.encode(&mut buf).unwrap();
308        assert_eq!(buf, expected);
309        assert_eq!(n, expected.len());
310    }
311
312    #[rstest]
313    #[case(i64::MIN,[Format::Int64.as_byte(),0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00])]
314    #[case(-1_i64,[Format::Int64.as_byte(),0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff])]
315    #[case(0_i64,[Format::Int64.as_byte(),0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00])]
316    #[case(i64::MAX,[Format::Int64.as_byte(),0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff])]
317    fn encode_int64<V: Encode<Vec<u8>>, E: AsRef<[u8]> + Sized>(
318        #[case] value: V,
319        #[case] expected: E,
320    ) {
321        let expected = expected.as_ref();
322
323        let mut buf = vec![];
324        let n = value.encode(&mut buf).unwrap();
325        assert_eq!(buf, expected);
326        assert_eq!(n, expected.len());
327    }
328
329    #[rstest]
330    #[case(0_i8,[0x00])]
331    #[case(0x7f_i8,[0x7f])]
332    #[case(0_u16,[0x00])]
333    #[case(0x7f_u16,[0x7f])]
334    #[case(0x80_u16,[Format::Uint8.as_byte(),0x80])]
335    #[case(0_i16,[0x00])]
336    #[case(0x7f_i16,[0x7f])]
337    #[case(0_u32,[0x00])]
338    #[case(0_u64,[0x00])]
339    #[case(0_u128,[0x00])]
340    #[case(0_i32,[0x00])]
341    #[case(0_i64,[0x00])]
342    #[case(0_i128,[0x00])]
343    #[case(3.0_f32,[0x03])]
344    fn encode_int_minimize<V: ToPrimitive, E: AsRef<[u8]> + Sized>(
345        #[case] value: V,
346        #[case] expected: E,
347    ) {
348        let expected = expected.as_ref();
349        let encoder = EncodeMinimizeInt(value);
350
351        let mut buf = vec![];
352        let n = encoder.encode(&mut buf).unwrap();
353        assert_eq!(buf, expected);
354        assert_eq!(n, expected.len());
355    }
356}