wasm_msgpack/encode/
mod.rs

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