embedded_msgpack/encode/
mod.rs

1#[cfg(feature = "serde")]
2pub mod serde;
3
4use crate::marker::Marker;
5
6use byteorder::{BigEndian, ByteOrder};
7#[allow(unused_imports)]
8use core::convert::TryFrom;
9use core::{convert::From, ops::Deref};
10use num_traits::cast::FromPrimitive;
11
12/// Error type indicating why serialization failed
13#[derive(Debug)]
14pub enum Error {
15    /// End of buffer was reached, before object could be serialized.
16    EndOfBuffer,
17    /// Value was out of bounds.
18    OutOfBounds,
19    /// Happens if the data type can not be serialized. For example if a sequence is not sized.
20    InvalidType,
21}
22
23impl ::core::fmt::Display for Error {
24    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::result::Result<(), core::fmt::Error> {
25        match self {
26            Error::OutOfBounds => f.write_str("Out of bounds"),
27            Error::InvalidType => f.write_str("Invalid type"),
28            Error::EndOfBuffer => f.write_str("End of buffer"),
29        }
30    }
31}
32
33#[cfg(feature = "std")]
34impl ::std::error::Error for Error {}
35
36pub trait SerializeIntoSlice {
37    fn write_into_slice(&self, buf: &mut [u8]) -> Result<usize, Error>;
38}
39
40pub fn serialize_u8(value: u8, buf: &mut [u8]) -> Result<usize, Error> {
41    if value < 0x80 {
42        if buf.is_empty() {
43            return Err(Error::EndOfBuffer);
44        }
45        buf[0] = value;
46        Ok(1)
47    } else {
48        if buf.len() < 2 {
49            return Err(Error::EndOfBuffer);
50        }
51        buf[0] = Marker::U8.to_u8();
52        buf[1] = value;
53        Ok(2)
54    }
55}
56pub fn serialize_u16(value: u16, buf: &mut [u8]) -> Result<usize, Error> {
57    if let Ok(value) = u8::try_from(value) {
58        serialize_u8(value, buf)
59    } else {
60        if buf.len() < 3 {
61            return Err(Error::EndOfBuffer);
62        }
63        buf[0] = Marker::U16.to_u8();
64        BigEndian::write_u16(&mut buf[1..], value);
65        Ok(3)
66    }
67}
68pub fn serialize_u32(value: u32, buf: &mut [u8]) -> Result<usize, Error> {
69    if let Ok(value) = u16::try_from(value) {
70        serialize_u16(value, buf)
71    } else {
72        if buf.len() < 5 {
73            return Err(Error::EndOfBuffer);
74        }
75        buf[0] = Marker::U32.to_u8();
76        BigEndian::write_u32(&mut buf[1..], value);
77        Ok(5)
78    }
79}
80#[cfg(feature = "u64")]
81pub fn serialize_u64(value: u64, buf: &mut [u8]) -> Result<usize, Error> {
82    if let Ok(value) = u32::try_from(value) {
83        serialize_u32(value, buf)
84    } else {
85        if buf.len() < 9 {
86            return Err(Error::EndOfBuffer);
87        }
88        buf[0] = Marker::U64.to_u8();
89        BigEndian::write_u64(&mut buf[1..], value);
90        Ok(9)
91    }
92}
93#[allow(clippy::single_match_else)]
94pub fn serialize_i8(value: i8, buf: &mut [u8]) -> Result<usize, Error> {
95    match value {
96        -32..=0x7f => {
97            if buf.is_empty() {
98                return Err(Error::EndOfBuffer);
99            }
100            buf[0] = value as u8;
101            Ok(1)
102        }
103        _ => {
104            if buf.len() < 2 {
105                return Err(Error::EndOfBuffer);
106            }
107            buf[0] = Marker::I8.to_u8();
108            buf[1] = value as u8;
109            Ok(2)
110        }
111    }
112}
113pub fn serialize_i16(value: i16, buf: &mut [u8]) -> Result<usize, Error> {
114    // if value <= i8::max_value() as i16 && value >= i8::min_value() as i16 {
115    if let Some(value) = u16::from_i16(value) {
116        serialize_u16(value, buf)
117    } else if let Some(value) = i8::from_i16(value) {
118        serialize_i8(value, buf)
119    } else {
120        if buf.len() < 3 {
121            return Err(Error::EndOfBuffer);
122        }
123        buf[0] = Marker::I16.to_u8();
124        BigEndian::write_i16(&mut buf[1..], value);
125        Ok(3)
126    }
127}
128pub fn serialize_i32(value: i32, buf: &mut [u8]) -> Result<usize, Error> {
129    // if value <= i16::max_value() as i32 && value >= i16::min_value() as i32 {
130    if let Some(value) = u32::from_i32(value) {
131        serialize_u32(value, buf)
132    } else if let Some(value) = i16::from_i32(value) {
133        serialize_i16(value, buf)
134    } else {
135        if buf.len() < 5 {
136            return Err(Error::EndOfBuffer);
137        }
138        buf[0] = Marker::I32.to_u8();
139        BigEndian::write_i32(&mut buf[1..], value);
140        Ok(5)
141    }
142}
143#[cfg(feature = "i64")]
144pub fn serialize_i64(value: i64, buf: &mut [u8]) -> Result<usize, Error> {
145    #[cfg(feature = "u64")]
146    if let Some(value) = u64::from_i64(value) {
147        return serialize_u64(value, buf);
148    }
149    if let Some(value) = i32::from_i64(value) {
150        serialize_i32(value, buf)
151    } else {
152        if buf.len() < 9 {
153            return Err(Error::EndOfBuffer);
154        }
155        buf[0] = Marker::I64.to_u8();
156        BigEndian::write_i64(&mut buf[1..], value);
157        Ok(9)
158    }
159}
160pub fn serialize_f32(value: f32, buf: &mut [u8]) -> Result<usize, Error> {
161    if buf.len() < 5 {
162        return Err(Error::EndOfBuffer);
163    }
164    buf[0] = Marker::F32.to_u8();
165    BigEndian::write_f32(&mut buf[1..], value);
166    Ok(5)
167}
168pub fn serialize_f64(value: f64, buf: &mut [u8]) -> Result<usize, Error> {
169    if buf.len() < 9 {
170        return Err(Error::EndOfBuffer);
171    }
172    buf[0] = Marker::F64.to_u8();
173    BigEndian::write_f64(&mut buf[1..], value);
174    Ok(9)
175}
176
177impl SerializeIntoSlice for u8 {
178    #[inline(always)]
179    fn write_into_slice(&self, buf: &mut [u8]) -> Result<usize, Error> { serialize_u8(*self, buf) }
180}
181impl SerializeIntoSlice for u16 {
182    #[inline(always)]
183    fn write_into_slice(&self, buf: &mut [u8]) -> Result<usize, Error> { serialize_u16(*self, buf) }
184}
185impl SerializeIntoSlice for u32 {
186    #[inline(always)]
187    fn write_into_slice(&self, buf: &mut [u8]) -> Result<usize, Error> { serialize_u32(*self, buf) }
188}
189#[cfg(feature = "u64")]
190impl SerializeIntoSlice for u64 {
191    #[inline(always)]
192    fn write_into_slice(&self, buf: &mut [u8]) -> Result<usize, Error> { serialize_u64(*self, buf) }
193}
194impl SerializeIntoSlice for i8 {
195    #[inline(always)]
196    fn write_into_slice(&self, buf: &mut [u8]) -> Result<usize, Error> { serialize_i8(*self, buf) }
197}
198impl SerializeIntoSlice for i16 {
199    #[inline(always)]
200    fn write_into_slice(&self, buf: &mut [u8]) -> Result<usize, Error> { serialize_i16(*self, buf) }
201}
202impl SerializeIntoSlice for i32 {
203    #[inline(always)]
204    fn write_into_slice(&self, buf: &mut [u8]) -> Result<usize, Error> { serialize_i32(*self, buf) }
205}
206#[cfg(feature = "i64")]
207impl SerializeIntoSlice for i64 {
208    #[inline(always)]
209    fn write_into_slice(&self, buf: &mut [u8]) -> Result<usize, Error> { serialize_i64(*self, buf) }
210}
211
212impl SerializeIntoSlice for f32 {
213    #[inline(always)]
214    fn write_into_slice(&self, buf: &mut [u8]) -> Result<usize, Error> { serialize_f32(*self, buf) }
215}
216impl SerializeIntoSlice for f64 {
217    #[inline(always)]
218    fn write_into_slice(&self, buf: &mut [u8]) -> Result<usize, Error> { serialize_f64(*self, buf) }
219}
220
221impl SerializeIntoSlice for bool {
222    fn write_into_slice(&self, buf: &mut [u8]) -> Result<usize, Error> {
223        if buf.is_empty() {
224            return Err(Error::EndOfBuffer);
225        }
226        buf[0] = if *self { Marker::True.to_u8() } else { Marker::False.to_u8() };
227        Ok(1)
228    }
229}
230
231impl<T> SerializeIntoSlice for Option<T>
232where T: SerializeIntoSlice
233{
234    fn write_into_slice(&self, buf: &mut [u8]) -> Result<usize, Error> {
235        if let Some(value) = self {
236            SerializeIntoSlice::write_into_slice(value, buf)
237        } else {
238            if buf.is_empty() {
239                return Err(Error::EndOfBuffer);
240            }
241            buf[0] = Marker::Null.to_u8();
242            Ok(1)
243        }
244    }
245}
246impl SerializeIntoSlice for () {
247    #[inline(always)]
248    fn write_into_slice(&self, _buf: &mut [u8]) -> Result<usize, Error> { Ok(0) }
249}
250
251#[cfg(any(feature = "alloc", feature = "std"))]
252extern crate alloc;
253#[cfg(any(feature = "alloc", feature = "std"))]
254use alloc::borrow::Cow;
255
256#[derive(PartialEq, Eq)]
257#[cfg_attr(any(test, feature = "derive-debug"), derive(core::fmt::Debug))]
258#[repr(transparent)]
259pub struct Binary<'a>(
260    #[cfg(not(any(feature = "alloc", feature = "std")))] &'a [u8],
261    #[cfg(any(feature = "alloc", feature = "std"))] Cow<'a, [u8]>,
262);
263
264impl<'a> Binary<'a> {
265    #[cfg(not(any(feature = "alloc", feature = "std")))]
266    #[inline]
267    pub const fn new(slice: &'a [u8]) -> Self { Binary(slice) }
268    #[cfg(any(feature = "alloc", feature = "std"))]
269    #[inline]
270    pub const fn new(slice: &'a [u8]) -> Self { Binary(Cow::Borrowed(slice)) }
271}
272
273impl<'a> Deref for Binary<'a> {
274    type Target = [u8];
275    #[cfg(not(any(feature = "alloc", feature = "std")))]
276    #[inline]
277    fn deref(&self) -> &Self::Target { &self.0 }
278    #[cfg(any(feature = "alloc", feature = "std"))]
279    #[inline]
280    fn deref(&self) -> &Self::Target { &self.0 }
281}
282impl<'a> From<&'a [u8]> for Binary<'a> {
283    #[inline]
284    fn from(slice: &'a [u8]) -> Self { Binary::new(slice) }
285}
286
287#[cfg(feature = "serde")]
288impl<'a> ::serde::Serialize for Binary<'a> {
289    fn serialize<S: ::serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { serializer.serialize_bytes(&self) }
290}
291#[cfg(feature = "serde")]
292struct BinaryVisitor;
293
294#[cfg(feature = "serde")]
295impl<'de> ::serde::de::Visitor<'de> for BinaryVisitor {
296    type Value = Binary<'de>;
297    fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { formatter.write_str("a byte array") }
298    fn visit_borrowed_bytes<E: ::serde::de::Error>(self, v: &'de [u8]) -> Result<Self::Value, E> { Ok(Binary::new(v)) }
299    #[cfg(any(feature = "alloc", feature = "std"))]
300    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
301    where A: ::serde::de::SeqAccess<'de> {
302        extern crate alloc;
303        #[cfg(not(feature = "std"))]
304        use alloc::vec::Vec;
305        let mut data = if let Some(len) = seq.size_hint() {
306            Vec::with_capacity(len)
307        } else {
308            Vec::new()
309        };
310        while let Some(e) = seq.next_element::<u8>()? {
311            data.push(e);
312        }
313        Ok(Binary(Cow::Owned(data)))
314    }
315}
316#[cfg(feature = "serde")]
317impl<'a> ::serde::Deserialize<'a> for Binary<'a> {
318    fn deserialize<D: ::serde::Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
319        deserializer.deserialize_bytes(BinaryVisitor)
320    }
321}
322
323/// # Panics
324///
325/// Will panic under the following conditions:
326///  - feature 'bin32' active: `n >= 2^32`
327///  - feature 'bin16' active: `n >= 2^16`
328///  - else: `n >= 2^8`
329impl<'a> SerializeIntoSlice for Binary<'a> {
330    fn write_into_slice(&self, buf: &mut [u8]) -> Result<usize, Error> {
331        let n = self.len();
332        if let Ok(n8) = u8::try_from(n) {
333            if buf.len() < 2 + n {
334                return Err(Error::EndOfBuffer);
335            }
336            buf[0] = Marker::Bin8.to_u8();
337            buf[1] = n8;
338            buf[2..(2 + n)].clone_from_slice(self);
339            return Ok(2 + n);
340        }
341        #[cfg(feature = "bin16")]
342        if let Ok(n16) = u16::try_from(n) {
343            if buf.len() < 3 + n {
344                return Err(Error::EndOfBuffer);
345            }
346            buf[0] = Marker::Bin16.to_u8();
347            BigEndian::write_u16(&mut buf[1..], n16);
348            buf[3..(3 + n)].clone_from_slice(self);
349            return Ok(3 + n);
350        }
351        #[cfg(feature = "bin32")]
352        if let Ok(n32) = u32::try_from(n) {
353            if buf.len() < 5 + n {
354                return Err(Error::EndOfBuffer);
355            }
356            buf[0] = Marker::Bin32.to_u8();
357            BigEndian::write_u32(&mut buf[1..], n32);
358            buf[5..(5 + n)].clone_from_slice(self);
359            return Ok(5 + n);
360        }
361        unimplemented!()
362    }
363}
364
365impl<K, V> SerializeIntoSlice for &(K, V)
366where
367    K: SerializeIntoSlice,
368    V: SerializeIntoSlice,
369{
370    #[inline(always)]
371    fn write_into_slice(&self, buf: &mut [u8]) -> Result<usize, Error> {
372        let index = serialize_map_kay_value(&self.0, &self.1, buf)?;
373        Ok(index)
374    }
375}
376
377/// # Panics
378///
379/// Will panic under the following conditions:
380///  - feature 'str32' active: `n >= 2^32`
381///  - feature 'str16' active: `n >= 2^16`
382///  - else: `n >= 2^8`
383impl SerializeIntoSlice for &str {
384    #[allow(clippy::cast_possible_truncation)]
385    fn write_into_slice(&self, buf: &mut [u8]) -> Result<usize, Error> {
386        let n = self.len();
387        match n {
388            // FIXSTR_SIZE
389            0..=0x1f => {
390                let header_len = 1;
391                if buf.len() < header_len + n {
392                    return Err(Error::EndOfBuffer);
393                }
394                buf[0] = Marker::FixStr(n as u8).to_u8();
395                buf[header_len..(header_len + n)].clone_from_slice(self.as_bytes());
396                Ok(header_len + n)
397            }
398            0x20..=0xff => {
399                let header_len = 2;
400                if buf.len() < header_len + n {
401                    return Err(Error::EndOfBuffer);
402                }
403                buf[0] = Marker::Str8.to_u8();
404                buf[1] = n as u8;
405                buf[header_len..(header_len + n)].clone_from_slice(self.as_bytes());
406                Ok(header_len + n)
407            }
408            _ => {
409                #[cfg(feature = "str16")]
410                if let Ok(n16) = u16::try_from(n) {
411                    let header_len = 3;
412                    if buf.len() < header_len + n {
413                        return Err(Error::EndOfBuffer);
414                    }
415                    buf[0] = Marker::Str16.to_u8();
416                    BigEndian::write_u16(&mut buf[1..], n16);
417                    buf[header_len..(header_len + n)].clone_from_slice(self.as_bytes());
418                    return Ok(header_len + n);
419                }
420                #[cfg(feature = "str32")]
421                if let Ok(n32) = u32::try_from(n) {
422                    let header_len = 5;
423                    if buf.len() < header_len + n {
424                        return Err(Error::EndOfBuffer);
425                    }
426                    buf[0] = Marker::Str32.to_u8();
427                    BigEndian::write_u32(&mut buf[1..], n32);
428                    buf[header_len..(header_len + n)].clone_from_slice(self.as_bytes());
429                    return Ok(header_len + n);
430                }
431                unimplemented!()
432            }
433        }
434    }
435}
436
437impl<K, V> SerializeIntoSlice for &[(K, V)]
438where
439    K: SerializeIntoSlice,
440    V: SerializeIntoSlice,
441{
442    fn write_into_slice(&self, buf: &mut [u8]) -> Result<usize, Error> {
443        // serialize_sequence(self, SequenceType::Map, buf)
444        let mut index = serialize_map_start(self.len(), buf)?;
445        for kv in self.iter() {
446            index += kv.write_into_slice(&mut buf[index..])?;
447        }
448        Ok(index)
449    }
450}
451
452impl<T> SerializeIntoSlice for &[T]
453where T: SerializeIntoSlice
454{
455    fn write_into_slice(&self, buf: &mut [u8]) -> Result<usize, Error> {
456        // serialize_sequence(self, SequenceType::Array, buf)
457        let mut index = serialize_array_start(self.len(), buf)?;
458        for i in self.iter() {
459            index += SerializeIntoSlice::write_into_slice(i, &mut buf[index..])?;
460        }
461        Ok(index)
462    }
463}
464
465#[derive(Copy, Clone)]
466pub enum SequenceType {
467    Array,
468    Map,
469}
470impl SequenceType {
471    pub fn serialize_start(self, n: usize, buf: &mut [u8]) -> Result<usize, Error> {
472        match self {
473            SequenceType::Array => serialize_array_start(n, buf),
474            SequenceType::Map => serialize_map_start(n, buf),
475        }
476    }
477}
478
479pub fn serialize_sequence<T: SerializeIntoSlice>(seq: &[T], typ: SequenceType, buf: &mut [u8]) -> Result<usize, Error> {
480    let mut index = typ.serialize_start(seq.len(), buf)?;
481    for i in seq.iter() {
482        index += SerializeIntoSlice::write_into_slice(i, &mut buf[index..])?;
483    }
484    Ok(index)
485}
486
487/// # Panics
488///
489/// Will panic under the following conditions:
490///  - feature 'array32' active: `n >= 2^32`
491///  - feature 'array16' active: `n >= 2^16`
492///  - else: `n >= 16`
493#[allow(clippy::cast_possible_truncation)]
494pub fn serialize_array_start(n: usize, buf: &mut [u8]) -> Result<usize, Error> {
495    if n <= crate::marker::FIXARRAY_SIZE as usize {
496        if buf.len() < 1 + n {
497            return Err(Error::EndOfBuffer);
498        }
499        buf[0] = Marker::FixArray(n as u8).to_u8();
500        Ok(1)
501    } else {
502        #[cfg(feature = "array16")]
503        if let Ok(n) = u16::try_from(n) {
504            buf[0] = Marker::Array16.to_u8();
505            BigEndian::write_u16(&mut buf[1..], n);
506            return Ok(3);
507        }
508        #[cfg(feature = "array32")]
509        if let Ok(n) = u32::try_from(n) {
510            buf[0] = Marker::Array32.to_u8();
511            BigEndian::write_u32(&mut buf[1..], n);
512            return Ok(5);
513        }
514        unimplemented!()
515    }
516}
517
518/// # Panics
519///
520/// Will panic under the following conditions:
521///  - feature 'map32' active: `n >= 2^32`
522///  - feature 'map16' active: `n >= 2^16`
523///  - else: `n >= 16`
524#[allow(clippy::cast_possible_truncation)]
525pub fn serialize_map_start(n: usize, buf: &mut [u8]) -> Result<usize, Error> {
526    if n <= crate::marker::FIXMAP_SIZE as usize {
527        if buf.len() < 1 + n {
528            return Err(Error::EndOfBuffer);
529        }
530        buf[0] = Marker::FixMap(n as u8).to_u8();
531        Ok(1)
532    } else {
533        #[cfg(feature = "map16")]
534        if let Ok(n) = u16::try_from(n) {
535            buf[0] = Marker::Map16.to_u8();
536            BigEndian::write_u16(&mut buf[1..], n);
537            return Ok(3);
538        }
539        #[cfg(feature = "map32")]
540        if let Ok(n) = u32::try_from(n) {
541            buf[0] = Marker::Map32.to_u8();
542            BigEndian::write_u32(&mut buf[1..], n);
543            return Ok(5);
544        }
545        unimplemented!()
546    }
547}
548pub fn serialize_map_kay_value<K: SerializeIntoSlice, V: SerializeIntoSlice>(key: &K, value: &V, buf: &mut [u8]) -> Result<usize, Error> {
549    let mut index = 0;
550    index += SerializeIntoSlice::write_into_slice(key, &mut buf[index..])?;
551    index += SerializeIntoSlice::write_into_slice(value, &mut buf[index..])?;
552    Ok(index)
553}