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