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