messagepack_serde/ser/
num.rs

1use messagepack_core::{
2    Encode,
3    encode::{Error, float::EncodeMinimizeFloat, int::EncodeMinimizeInt},
4    io::IoWrite,
5};
6use num_traits::{ToPrimitive, float::FloatCore};
7
8/// Decide how numeric values are encoded.
9pub trait NumEncoder<W: IoWrite> {
10    /// decide encode i8
11    fn encode_i8(v: i8, writer: &mut W) -> Result<usize, Error<W::Error>>;
12    /// decide encode i16
13    fn encode_i16(v: i16, writer: &mut W) -> Result<usize, Error<W::Error>>;
14    /// decide encode i32
15    fn encode_i32(v: i32, writer: &mut W) -> Result<usize, Error<W::Error>>;
16    /// decide encode i64
17    fn encode_i64(v: i64, writer: &mut W) -> Result<usize, Error<W::Error>>;
18    /// decide encode i128
19    fn encode_i128(v: i128, writer: &mut W) -> Result<usize, Error<W::Error>>;
20    /// decide encode u8
21    fn encode_u8(v: u8, writer: &mut W) -> Result<usize, Error<W::Error>>;
22    /// decide encode u16
23    fn encode_u16(v: u16, writer: &mut W) -> Result<usize, Error<W::Error>>;
24    /// decide encode u32
25    fn encode_u32(v: u32, writer: &mut W) -> Result<usize, Error<W::Error>>;
26    /// decide encode u64
27    fn encode_u64(v: u64, writer: &mut W) -> Result<usize, Error<W::Error>>;
28    /// decide encode u128
29    fn encode_u128(v: u128, writer: &mut W) -> Result<usize, Error<W::Error>>;
30    /// decide encode f32
31    fn encode_f32(v: f32, writer: &mut W) -> Result<usize, Error<W::Error>>;
32    /// decide encode f64
33    fn encode_f64(v: f64, writer: &mut W) -> Result<usize, Error<W::Error>>;
34}
35
36/// Encode a given numeric value exactly using its native format.
37///
38/// This does not minimise or convert, so the value is written as is.
39///
40/// ## Examples
41///
42/// `u8` is encoded to `positive fixint` or `uint 8`
43///
44/// ```rust
45/// use serde::Serialize;
46/// use messagepack_serde::ser::{to_slice_with_config, Exact};
47///
48/// let mut buf = [0_u8;1];
49/// to_slice_with_config(&1_u8, &mut buf, Exact).unwrap();
50///
51/// let expected = [1_u8]; // 1 encoded in `positive fixint`
52/// assert_eq!(buf,expected);
53/// ```
54///  
55/// `u16` is encoded to `uint 16`
56///
57/// ```rust
58/// use serde::Serialize;
59/// use messagepack_serde::ser::{to_slice_with_config, Exact};
60///
61/// let mut buf = [0_u8;3];
62/// to_slice_with_config(&1_u16, &mut buf, Exact).unwrap();
63///
64/// let expected = [0xcd_u8, 0x00_u8, 1_u8]; // 1 encoded in `uint 16`
65/// assert_eq!(buf,expected);
66/// ```
67pub struct Exact;
68
69impl<W: IoWrite> NumEncoder<W> for Exact {
70    fn encode_i8(v: i8, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
71        v.encode(writer)
72    }
73
74    fn encode_i16(v: i16, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
75        v.encode(writer)
76    }
77
78    fn encode_i32(v: i32, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
79        v.encode(writer)
80    }
81
82    fn encode_i64(v: i64, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
83        v.encode(writer)
84    }
85
86    fn encode_i128(v: i128, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
87        v.encode(writer)
88    }
89
90    fn encode_u8(v: u8, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
91        v.encode(writer)
92    }
93
94    fn encode_u16(v: u16, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
95        v.encode(writer)
96    }
97
98    fn encode_u32(v: u32, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
99        v.encode(writer)
100    }
101
102    fn encode_u64(v: u64, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
103        v.encode(writer)
104    }
105
106    fn encode_u128(v: u128, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
107        v.encode(writer)
108    }
109
110    fn encode_f32(v: f32, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
111        v.encode(writer)
112    }
113
114    fn encode_f64(v: f64, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
115        v.encode(writer)
116    }
117}
118
119/// Encode a given numeric value in a lossless minimised format without changing its original format.
120///
121/// This encoder minimises the encoded size of a numeric value without any loss of information or change in its inherent type.
122/// For integer types, it encodes the value using the smallest integer format that can exactly represent the original value.
123/// For floating-point types, it encodes the value using the smallest floating-point format that preserves its precision.
124///
125/// ## Examples
126///
127/// If there is no loss in a smaller format, it is encoded with that value
128///
129/// ```rust
130/// use serde::Serialize;
131/// use messagepack_serde::ser::{to_slice_with_config, LosslessMinimize};
132///
133/// let mut buf = [0_u8;1];
134/// to_slice_with_config(&1_u16, &mut buf, LosslessMinimize).unwrap();
135/// let expected = [1_u8]; // 1 encoded in `positive fixint`
136/// assert_eq!(buf,expected);
137/// ```
138///
139/// Floating point is encoded as floating point type
140///
141/// ```rust
142/// use serde::Serialize;
143/// use messagepack_serde::ser::{to_slice_with_config, LosslessMinimize};
144///
145/// let mut buf = [0_u8;5];
146/// to_slice_with_config(&1.0_f32, &mut buf, LosslessMinimize).unwrap();
147///
148/// let expected = [0xca,0x3f,0x80,0x00,0x00]; // 1.0 encoded in `float 32`
149/// assert_eq!(buf,expected);
150/// ```
151///
152/// If floating point can be encoded without loss, it will be encoded in a smaller format
153///
154/// ```rust
155/// use serde::Serialize;
156/// use messagepack_serde::ser::{to_slice_with_config, LosslessMinimize};
157///
158/// let mut buf = [0_u8;5];
159/// to_slice_with_config(&1.0_f64, &mut buf, LosslessMinimize).unwrap();
160///
161/// let expected = [0xca,0x3f,0x80,0x00,0x00]; // 1.0 encoded in `float 32`
162/// assert_eq!(buf,expected);
163/// ```
164///
165/// `0.1` is encoded as `float 64` due to loss when converted to `f32
166///
167/// ```rust
168/// use serde::Serialize;
169/// use messagepack_serde::ser::{to_slice_with_config, LosslessMinimize};
170///
171/// let mut buf = [0_u8;9];
172/// to_slice_with_config(&0.1_f64, &mut buf, LosslessMinimize).unwrap();
173///
174/// let expected = [0xcb,0x3f,0xb9,0x99,0x99,0x99,0x99,0x99,0x9a]; // 0.1 encoded in `float 64`
175/// assert_eq!(buf,expected);
176/// ```
177pub struct LosslessMinimize;
178
179impl LosslessMinimize {
180    fn encode_int<T: ToPrimitive, W: IoWrite>(
181        v: T,
182        writer: &mut W,
183    ) -> Result<usize, Error<<W as IoWrite>::Error>> {
184        EncodeMinimizeInt(v).encode(writer)
185    }
186
187    fn encode_float<T: Into<EncodeMinimizeFloat>, W: IoWrite>(
188        v: T,
189        writer: &mut W,
190    ) -> Result<usize, Error<<W as IoWrite>::Error>> {
191        let encoder: EncodeMinimizeFloat = v.into();
192        let size = encoder.encode(writer)?;
193        Ok(size)
194    }
195}
196
197impl<W: IoWrite> NumEncoder<W> for LosslessMinimize {
198    fn encode_i8(v: i8, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
199        Self::encode_int(v, writer)
200    }
201
202    fn encode_i16(v: i16, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
203        Self::encode_int(v, writer)
204    }
205
206    fn encode_i32(v: i32, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
207        Self::encode_int(v, writer)
208    }
209
210    fn encode_i64(v: i64, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
211        Self::encode_int(v, writer)
212    }
213
214    fn encode_i128(v: i128, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
215        Self::encode_int(v, writer)
216    }
217
218    fn encode_u8(v: u8, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
219        Self::encode_int(v, writer)
220    }
221
222    fn encode_u16(v: u16, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
223        Self::encode_int(v, writer)
224    }
225
226    fn encode_u32(v: u32, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
227        Self::encode_int(v, writer)
228    }
229
230    fn encode_u64(v: u64, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
231        Self::encode_int(v, writer)
232    }
233
234    fn encode_u128(v: u128, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
235        Self::encode_int(v, writer)
236    }
237
238    fn encode_f32(v: f32, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
239        Self::encode_float(v, writer)
240    }
241
242    fn encode_f64(v: f64, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
243        Self::encode_float(v, writer)
244    }
245}
246
247/// Encode a given numeric value by aggressively minimising its format.
248///
249/// If the float is finite and its fractional part is zero, it first tries to encode it as an integer.
250/// If this conversion fails, it falls back to encoding the value as a float.
251///
252/// ## Examples
253///
254/// If there is no loss in a smaller format, it is encoded with that value
255///
256/// ```rust
257/// use serde::Serialize;
258/// use messagepack_serde::ser::{to_slice_with_config, AggressiveMinimize};
259///
260/// let mut buf = [0_u8;1];
261/// to_slice_with_config(&1_u16, &mut buf, AggressiveMinimize).unwrap();
262///
263/// let expected = [1_u8]; // 1 encoded in `positive fixint`
264/// assert_eq!(buf,expected);
265/// ```
266///
267/// Floating point without fractional part is encoded as `int`
268///
269/// ```rust
270/// use serde::Serialize;
271/// use messagepack_serde::ser::{to_slice_with_config, AggressiveMinimize};
272///
273/// let mut buf = [0_u8;1];
274/// to_slice_with_config(&1.0_f32, &mut buf, AggressiveMinimize).unwrap();
275///
276/// let expected = [1_u8]; // 1 encoded in `positive fixint`
277/// assert_eq!(buf,expected);
278/// ```
279///
280/// `f64` is encoded in the same way as `f32`.
281///
282/// ```rust
283/// use serde::Serialize;
284/// use messagepack_serde::ser::{to_slice_with_config, AggressiveMinimize};
285///
286/// let mut buf = [0_u8;1];
287/// to_slice_with_config(&1.0_f64, &mut buf, AggressiveMinimize).unwrap();
288///
289/// let expected = [1_u8]; // 1 encoded in `positive fixint`
290/// assert_eq!(buf,expected);
291/// ```
292pub struct AggressiveMinimize;
293
294impl AggressiveMinimize {
295    fn encode_int<T: ToPrimitive, W: IoWrite>(
296        v: T,
297        writer: &mut W,
298    ) -> Result<usize, Error<<W as IoWrite>::Error>> {
299        EncodeMinimizeInt(v).encode(writer)
300    }
301
302    fn encode_float<T: FloatCore + Into<EncodeMinimizeFloat>, W: IoWrite>(
303        v: T,
304        writer: &mut W,
305    ) -> Result<usize, Error<<W as IoWrite>::Error>> {
306        if v.is_finite() && v.fract().is_zero() {
307            let size = Self::encode_int(v, writer).or_else(|_| v.into().encode(writer))?;
308            Ok(size)
309        } else {
310            let size = v.into().encode(writer)?;
311            Ok(size)
312        }
313    }
314}
315
316impl<W: IoWrite> NumEncoder<W> for AggressiveMinimize {
317    fn encode_i8(v: i8, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
318        Self::encode_int(v, writer)
319    }
320
321    fn encode_i16(v: i16, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
322        Self::encode_int(v, writer)
323    }
324
325    fn encode_i32(v: i32, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
326        Self::encode_int(v, writer)
327    }
328
329    fn encode_i64(v: i64, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
330        Self::encode_int(v, writer)
331    }
332
333    fn encode_i128(v: i128, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
334        Self::encode_int(v, writer)
335    }
336
337    fn encode_u8(v: u8, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
338        Self::encode_int(v, writer)
339    }
340
341    fn encode_u16(v: u16, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
342        Self::encode_int(v, writer)
343    }
344
345    fn encode_u32(v: u32, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
346        Self::encode_int(v, writer)
347    }
348
349    fn encode_u64(v: u64, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
350        Self::encode_int(v, writer)
351    }
352
353    fn encode_u128(v: u128, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
354        Self::encode_int(v, writer)
355    }
356
357    fn encode_f32(v: f32, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
358        Self::encode_float(v, writer)
359    }
360
361    fn encode_f64(v: f64, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
362        Self::encode_float(v, writer)
363    }
364}