Skip to main content

multi_cbor/
ser.rs

1//! Serialize a Rust data structure to CBOR data.
2
3#[cfg(feature = "alloc")]
4use alloc::vec::Vec;
5
6#[cfg(feature = "std")]
7pub use crate::write::IoWrite;
8pub use crate::write::{SliceWrite, Write};
9
10use crate::error::{Error, Result};
11use half::f16;
12use serde::ser::{self, Serialize};
13#[cfg(feature = "std")]
14use std::io;
15
16use crate::tags::{get_tag, CBOR_NEWTYPE_NAME};
17
18/// Serializes a value to a vector.
19#[cfg(any(feature = "std", feature = "alloc"))]
20pub fn to_vec<T>(value: &T) -> Result<Vec<u8>>
21where
22    T: ser::Serialize,
23{
24    let mut vec = Vec::new();
25    value.serialize(&mut Serializer::new(&mut vec))?;
26    Ok(vec)
27}
28
29/// Serializes a value to a vector in packed format.
30#[cfg(feature = "std")]
31pub fn to_vec_packed<T>(value: &T) -> Result<Vec<u8>>
32where
33    T: ser::Serialize,
34{
35    let mut vec = Vec::new();
36    value.serialize(&mut Serializer::new(&mut IoWrite::new(&mut vec)).packed_format())?;
37    Ok(vec)
38}
39
40/// Serializes a value to a writer.
41#[cfg(feature = "std")]
42pub fn to_writer<W, T>(writer: W, value: &T) -> Result<()>
43where
44    W: io::Write,
45    T: ser::Serialize,
46{
47    value.serialize(&mut Serializer::new(&mut IoWrite::new(writer)))
48}
49
50/// A structure for serializing Rust values to CBOR.
51#[derive(Debug)]
52pub struct Serializer<W> {
53    writer: W,
54    packed: bool,
55    enum_as_map: bool,
56}
57
58impl<W> Serializer<W>
59where
60    W: Write,
61{
62    /// Creates a new CBOR serializer.
63    ///
64    /// `to_vec` and `to_writer` should normally be used instead of this method.
65    #[inline]
66    pub const fn new(writer: W) -> Self {
67        Self {
68            writer,
69            packed: false,
70            enum_as_map: true,
71        }
72    }
73
74    /// Choose concise/packed format for serializer.
75    ///
76    /// In the packed format enum variant names and field names
77    /// are replaced with numeric indizes to conserve space.
78    #[must_use]
79    pub const fn packed_format(mut self) -> Self {
80        self.packed = true;
81        self
82    }
83
84    /// Enable old enum format used by `multi_cbor` versions <= v0.9.
85    ///
86    /// The `legacy_enums` option determines how enums are encoded.
87    ///
88    /// This makes no difference when encoding and decoding enums using
89    /// this crate, but it shows up when decoding to a `Value` or decoding
90    /// in other languages.
91    ///
92    /// # Examples
93    ///
94    /// Given the following enum
95    ///
96    /// ```rust
97    /// enum Enum {
98    ///     Unit,
99    ///     NewType(i32),
100    ///     Tuple(String, bool),
101    ///     Struct{ x: i32, y: i32 },
102    /// }
103    /// ```
104    /// we will give the `Value` with the same encoding for each case using
105    /// JSON notation.
106    ///
107    /// ## Default encodings
108    ///
109    /// * `Enum::Unit` encodes as `"Unit"`
110    /// * `Enum::NewType(10)` encodes as `{"NewType": 10}`
111    /// * `Enum::Tuple("x", true)` encodes as `{"Tuple": ["x", true]}`
112    ///
113    /// ## Legacy encodings
114    ///
115    /// * `Enum::Unit` encodes as `"Unit"`
116    /// * `Enum::NewType(10)` encodes as `["NewType", 10]`
117    /// * `Enum::Tuple("x", true)` encodes as `["Tuple", "x", true]`
118    /// * `Enum::Struct{ x: 5, y: -5 }` encodes as `["Struct", {"x": 5, "y": -5}]`
119    #[must_use]
120    pub const fn legacy_enums(mut self) -> Self {
121        self.enum_as_map = false;
122        self
123    }
124
125    /// Writes a CBOR self-describe tag to the stream.
126    ///
127    /// Tagging allows a decoder to distinguish different file formats based on their content
128    /// without further information.
129    #[inline]
130    pub fn self_describe(&mut self) -> Result<()> {
131        let mut buf = [6 << 5 | 25, 0, 0];
132        buf[1..].copy_from_slice(&55799u16.to_be_bytes());
133        self.writer
134            .write_all(&buf)
135            .map_err(core::convert::Into::into)
136    }
137
138    /// Unwrap the `Writer` from the `Serializer`.
139    #[inline]
140    pub fn into_inner(self) -> W {
141        self.writer
142    }
143
144    #[inline]
145    fn write_u8(&mut self, major: u8, value: u8) -> Result<()> {
146        if value <= 0x17 {
147            self.writer.write_all(&[major << 5 | value])
148        } else {
149            let buf = [major << 5 | 24, value];
150            self.writer.write_all(&buf)
151        }
152        .map_err(core::convert::Into::into)
153    }
154
155    #[inline]
156    fn write_u16(&mut self, major: u8, value: u16) -> Result<()> {
157        if u8::try_from(value).is_ok() {
158            self.write_u8(major, value as u8)
159        } else {
160            let mut buf = [major << 5 | 25, 0, 0];
161            buf[1..].copy_from_slice(&value.to_be_bytes());
162            self.writer
163                .write_all(&buf)
164                .map_err(core::convert::Into::into)
165        }
166    }
167
168    #[inline]
169    fn write_u32(&mut self, major: u8, value: u32) -> Result<()> {
170        if u16::try_from(value).is_ok() {
171            self.write_u16(major, value as u16)
172        } else {
173            let mut buf = [major << 5 | 26, 0, 0, 0, 0];
174            buf[1..].copy_from_slice(&value.to_be_bytes());
175            self.writer
176                .write_all(&buf)
177                .map_err(core::convert::Into::into)
178        }
179    }
180
181    #[inline]
182    fn write_u64(&mut self, major: u8, value: u64) -> Result<()> {
183        if u32::try_from(value).is_ok() {
184            self.write_u32(major, value as u32)
185        } else {
186            let mut buf = [major << 5 | 27, 0, 0, 0, 0, 0, 0, 0, 0];
187            buf[1..].copy_from_slice(&value.to_be_bytes());
188            self.writer
189                .write_all(&buf)
190                .map_err(core::convert::Into::into)
191        }
192    }
193
194    #[inline]
195    fn serialize_collection(
196        &mut self,
197        major: u8,
198        len: Option<usize>,
199    ) -> Result<CollectionSerializer<'_, W>> {
200        let needs_eof = if let Some(len) = len {
201            self.write_u64(major, len as u64)?;
202            false
203        } else {
204            self.writer
205                .write_all(&[major << 5 | 31])
206                .map_err(core::convert::Into::into)?;
207            true
208        };
209
210        Ok(CollectionSerializer {
211            ser: self,
212            needs_eof,
213        })
214    }
215}
216
217impl<'a, W> ser::Serializer for &'a mut Serializer<W>
218where
219    W: Write,
220{
221    type Ok = ();
222    type Error = Error;
223
224    type SerializeSeq = CollectionSerializer<'a, W>;
225    type SerializeTuple = &'a mut Serializer<W>;
226    type SerializeTupleStruct = &'a mut Serializer<W>;
227    type SerializeTupleVariant = &'a mut Serializer<W>;
228    type SerializeMap = CollectionSerializer<'a, W>;
229    type SerializeStruct = StructSerializer<'a, W>;
230    type SerializeStructVariant = StructSerializer<'a, W>;
231
232    #[inline]
233    fn serialize_bool(self, value: bool) -> Result<()> {
234        let value = if value { 0xf5 } else { 0xf4 };
235        self.writer
236            .write_all(&[value])
237            .map_err(core::convert::Into::into)
238    }
239
240    #[inline]
241    fn serialize_i8(self, value: i8) -> Result<()> {
242        if value < 0 {
243            self.write_u8(1, -(value + 1) as u8)
244        } else {
245            self.write_u8(0, value as u8)
246        }
247    }
248
249    #[inline]
250    fn serialize_i16(self, value: i16) -> Result<()> {
251        if value < 0 {
252            self.write_u16(1, -(value + 1) as u16)
253        } else {
254            self.write_u16(0, value as u16)
255        }
256    }
257
258    #[inline]
259    fn serialize_i32(self, value: i32) -> Result<()> {
260        if value < 0 {
261            self.write_u32(1, -(value + 1) as u32)
262        } else {
263            self.write_u32(0, value as u32)
264        }
265    }
266
267    #[inline]
268    fn serialize_i64(self, value: i64) -> Result<()> {
269        if value < 0 {
270            self.write_u64(1, -(value + 1) as u64)
271        } else {
272            self.write_u64(0, value as u64)
273        }
274    }
275
276    #[inline]
277    fn serialize_i128(self, value: i128) -> Result<()> {
278        if value < 0 {
279            if -(value + 1) > i128::from(u64::MAX) {
280                return Err(Error::message("The number can't be stored in CBOR"));
281            }
282            self.write_u64(1, -(value + 1) as u64)
283        } else {
284            if value > i128::from(u64::MAX) {
285                return Err(Error::message("The number can't be stored in CBOR"));
286            }
287            self.write_u64(0, value as u64)
288        }
289    }
290
291    #[inline]
292    fn serialize_u8(self, value: u8) -> Result<()> {
293        self.write_u8(0, value)
294    }
295
296    #[inline]
297    fn serialize_u16(self, value: u16) -> Result<()> {
298        self.write_u16(0, value)
299    }
300
301    #[inline]
302    fn serialize_u32(self, value: u32) -> Result<()> {
303        self.write_u32(0, value)
304    }
305
306    #[inline]
307    fn serialize_u64(self, value: u64) -> Result<()> {
308        self.write_u64(0, value)
309    }
310
311    #[inline]
312    fn serialize_u128(self, value: u128) -> Result<()> {
313        if value > u128::from(u64::MAX) {
314            return Err(Error::message("The number can't be stored in CBOR"));
315        }
316        self.write_u64(0, value as u64)
317    }
318
319    #[inline]
320    #[allow(clippy::float_cmp)]
321    fn serialize_f32(self, value: f32) -> Result<()> {
322        if value.is_infinite() {
323            if value.is_sign_positive() {
324                self.writer.write_all(&[0xf9, 0x7c, 0x00])
325            } else {
326                self.writer.write_all(&[0xf9, 0xfc, 0x00])
327            }
328        } else if value.is_nan() {
329            self.writer.write_all(&[0xf9, 0x7e, 0x00])
330        } else if f32::from(f16::from_f32(value)) == value {
331            let mut buf = [0xf9, 0, 0];
332            buf[1..].copy_from_slice(&f16::from_f32(value).to_bits().to_be_bytes());
333            self.writer.write_all(&buf)
334        } else {
335            let mut buf = [0xfa, 0, 0, 0, 0];
336            buf[1..].copy_from_slice(&value.to_bits().to_be_bytes());
337            self.writer.write_all(&buf)
338        }
339        .map_err(core::convert::Into::into)
340    }
341
342    #[inline]
343    #[allow(clippy::float_cmp)]
344    fn serialize_f64(self, value: f64) -> Result<()> {
345        if !value.is_finite() || f64::from(value as f32) == value {
346            self.serialize_f32(value as f32)
347        } else {
348            let mut buf = [0xfb, 0, 0, 0, 0, 0, 0, 0, 0];
349            buf[1..].copy_from_slice(&value.to_bits().to_be_bytes());
350            self.writer
351                .write_all(&buf)
352                .map_err(core::convert::Into::into)
353        }
354    }
355
356    #[inline]
357    fn serialize_char(self, value: char) -> Result<()> {
358        // A char encoded as UTF-8 takes 4 bytes at most.
359        let mut buf = [0; 4];
360        self.serialize_str(value.encode_utf8(&mut buf))
361    }
362
363    #[inline]
364    fn serialize_str(self, value: &str) -> Result<()> {
365        self.write_u64(3, value.len() as u64)?;
366        self.writer
367            .write_all(value.as_bytes())
368            .map_err(core::convert::Into::into)
369    }
370
371    #[inline]
372    fn serialize_bytes(self, value: &[u8]) -> Result<()> {
373        self.write_u64(2, value.len() as u64)?;
374        self.writer
375            .write_all(value)
376            .map_err(core::convert::Into::into)
377    }
378
379    #[inline]
380    fn serialize_unit(self) -> Result<()> {
381        self.serialize_none()
382    }
383
384    #[inline]
385    fn serialize_some<T>(self, value: &T) -> Result<()>
386    where
387        T: ?Sized + ser::Serialize,
388    {
389        value.serialize(self)
390    }
391
392    #[inline]
393    fn serialize_none(self) -> Result<()> {
394        self.writer
395            .write_all(&[0xf6])
396            .map_err(core::convert::Into::into)
397    }
398
399    #[inline]
400    fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
401        self.serialize_unit()
402    }
403
404    #[inline]
405    fn serialize_unit_variant(
406        self,
407        _name: &'static str,
408        variant_index: u32,
409        variant: &'static str,
410    ) -> Result<()> {
411        if self.packed {
412            self.serialize_u32(variant_index)
413        } else {
414            self.serialize_str(variant)
415        }
416    }
417
418    #[inline]
419    fn serialize_newtype_struct<T>(self, name: &'static str, value: &T) -> Result<()>
420    where
421        T: ?Sized + ser::Serialize,
422    {
423        if name == CBOR_NEWTYPE_NAME {
424            if let Some(tag) = get_tag() {
425                self.write_u64(6, tag)?;
426            }
427        }
428        value.serialize(self)
429    }
430
431    #[inline]
432    fn serialize_newtype_variant<T>(
433        self,
434        name: &'static str,
435        variant_index: u32,
436        variant: &'static str,
437        value: &T,
438    ) -> Result<()>
439    where
440        T: ?Sized + ser::Serialize,
441    {
442        if self.enum_as_map {
443            self.write_u64(5, 1u64)?;
444            variant.serialize(&mut *self)?;
445        } else {
446            self.writer
447                .write_all(&[4 << 5 | 2])
448                .map_err(core::convert::Into::into)?;
449            self.serialize_unit_variant(name, variant_index, variant)?;
450        }
451        value.serialize(self)
452    }
453
454    #[inline]
455    fn serialize_seq(self, len: Option<usize>) -> Result<CollectionSerializer<'a, W>> {
456        self.serialize_collection(4, len)
457    }
458
459    #[inline]
460    fn serialize_tuple(self, len: usize) -> Result<&'a mut Serializer<W>> {
461        self.write_u64(4, len as u64)?;
462        Ok(self)
463    }
464
465    #[inline]
466    fn serialize_tuple_struct(
467        self,
468        _name: &'static str,
469        len: usize,
470    ) -> Result<&'a mut Serializer<W>> {
471        self.serialize_tuple(len)
472    }
473
474    #[inline]
475    fn serialize_tuple_variant(
476        self,
477        name: &'static str,
478        variant_index: u32,
479        variant: &'static str,
480        len: usize,
481    ) -> Result<&'a mut Serializer<W>> {
482        if self.enum_as_map {
483            self.write_u64(5, 1u64)?;
484            variant.serialize(&mut *self)?;
485            self.serialize_tuple(len)
486        } else {
487            self.write_u64(4, (len + 1) as u64)?;
488            self.serialize_unit_variant(name, variant_index, variant)?;
489            Ok(self)
490        }
491    }
492
493    #[inline]
494    fn serialize_map(self, len: Option<usize>) -> Result<CollectionSerializer<'a, W>> {
495        self.serialize_collection(5, len)
496    }
497
498    #[cfg(not(feature = "std"))]
499    fn collect_str<T: ?Sized + core::fmt::Display>(self, value: &T) -> Result<()> {
500        use crate::write::FmtWrite;
501        use core::fmt::Write;
502
503        let mut w = FmtWrite::new(&mut self.writer);
504        write!(w, "{value}")?;
505        Ok(())
506    }
507
508    #[inline]
509    fn serialize_struct(self, _name: &'static str, len: usize) -> Result<StructSerializer<'a, W>> {
510        self.write_u64(5, len as u64)?;
511        Ok(StructSerializer { ser: self, idx: 0 })
512    }
513
514    #[inline]
515    fn serialize_struct_variant(
516        self,
517        name: &'static str,
518        variant_index: u32,
519        variant: &'static str,
520        len: usize,
521    ) -> Result<StructSerializer<'a, W>> {
522        if self.enum_as_map {
523            self.write_u64(5, 1u64)?;
524        } else {
525            self.writer
526                .write_all(&[4 << 5 | 2])
527                .map_err(core::convert::Into::into)?;
528        }
529        self.serialize_unit_variant(name, variant_index, variant)?;
530        self.serialize_struct(name, len)
531    }
532
533    #[inline]
534    fn is_human_readable(&self) -> bool {
535        false
536    }
537}
538
539impl<W> ser::SerializeTuple for &mut Serializer<W>
540where
541    W: Write,
542{
543    type Ok = ();
544    type Error = Error;
545
546    #[inline]
547    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
548    where
549        T: ?Sized + ser::Serialize,
550    {
551        value.serialize(&mut **self)
552    }
553
554    #[inline]
555    fn end(self) -> Result<()> {
556        Ok(())
557    }
558}
559
560impl<W> ser::SerializeTupleStruct for &mut Serializer<W>
561where
562    W: Write,
563{
564    type Ok = ();
565    type Error = Error;
566
567    #[inline]
568    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
569    where
570        T: ?Sized + ser::Serialize,
571    {
572        value.serialize(&mut **self)
573    }
574
575    #[inline]
576    fn end(self) -> Result<()> {
577        Ok(())
578    }
579}
580
581impl<W> ser::SerializeTupleVariant for &mut Serializer<W>
582where
583    W: Write,
584{
585    type Ok = ();
586    type Error = Error;
587
588    #[inline]
589    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
590    where
591        T: ?Sized + ser::Serialize,
592    {
593        value.serialize(&mut **self)
594    }
595
596    #[inline]
597    fn end(self) -> Result<()> {
598        Ok(())
599    }
600}
601
602#[doc(hidden)]
603pub struct StructSerializer<'a, W> {
604    ser: &'a mut Serializer<W>,
605    idx: u32,
606}
607
608impl<W> StructSerializer<'_, W>
609where
610    W: Write,
611{
612    #[inline]
613    fn serialize_field_inner<T>(&mut self, key: &'static str, value: &T) -> Result<()>
614    where
615        T: ?Sized + ser::Serialize,
616    {
617        if self.ser.packed {
618            self.idx.serialize(&mut *self.ser)?;
619        } else {
620            key.serialize(&mut *self.ser)?;
621        }
622        value.serialize(&mut *self.ser)?;
623        self.idx += 1;
624        Ok(())
625    }
626
627    #[inline]
628    const fn skip_field_inner(&mut self, _key: &'static str) {
629        self.idx += 1;
630    }
631
632    #[inline]
633    #[allow(clippy::unused_self)] // consumes `self` to prevent further field writes after `end`
634    const fn end_inner(self) {
635        // Takes `self` by value to consume the `StructSerializer` and prevent
636        // further field writes after `end`. The body needs no `self` data.
637    }
638}
639
640impl<W> ser::SerializeStruct for StructSerializer<'_, W>
641where
642    W: Write,
643{
644    type Ok = ();
645    type Error = Error;
646
647    #[inline]
648    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
649    where
650        T: ?Sized + ser::Serialize,
651    {
652        self.serialize_field_inner(key, value)
653    }
654
655    #[inline]
656    fn skip_field(&mut self, key: &'static str) -> Result<()> {
657        self.skip_field_inner(key);
658        Ok(())
659    }
660
661    #[inline]
662    fn end(self) -> Result<()> {
663        self.end_inner();
664        Ok(())
665    }
666}
667
668impl<W> ser::SerializeStructVariant for StructSerializer<'_, W>
669where
670    W: Write,
671{
672    type Ok = ();
673    type Error = Error;
674
675    #[inline]
676    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
677    where
678        T: ?Sized + ser::Serialize,
679    {
680        self.serialize_field_inner(key, value)
681    }
682
683    #[inline]
684    fn skip_field(&mut self, key: &'static str) -> Result<()> {
685        self.skip_field_inner(key);
686        Ok(())
687    }
688
689    #[inline]
690    fn end(self) -> Result<()> {
691        self.end_inner();
692        Ok(())
693    }
694}
695
696#[doc(hidden)]
697pub struct CollectionSerializer<'a, W> {
698    ser: &'a mut Serializer<W>,
699    needs_eof: bool,
700}
701
702impl<W> CollectionSerializer<'_, W>
703where
704    W: Write,
705{
706    #[inline]
707    fn end_inner(self) -> Result<()> {
708        if self.needs_eof {
709            self.ser
710                .writer
711                .write_all(&[0xff])
712                .map_err(core::convert::Into::into)
713        } else {
714            Ok(())
715        }
716    }
717}
718
719impl<W> ser::SerializeSeq for CollectionSerializer<'_, W>
720where
721    W: Write,
722{
723    type Ok = ();
724    type Error = Error;
725
726    #[inline]
727    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
728    where
729        T: ?Sized + ser::Serialize,
730    {
731        value.serialize(&mut *self.ser)
732    }
733
734    #[inline]
735    fn end(self) -> Result<()> {
736        self.end_inner()
737    }
738}
739
740impl<W> ser::SerializeMap for CollectionSerializer<'_, W>
741where
742    W: Write,
743{
744    type Ok = ();
745    type Error = Error;
746
747    #[inline]
748    fn serialize_key<T>(&mut self, key: &T) -> Result<()>
749    where
750        T: ?Sized + ser::Serialize,
751    {
752        key.serialize(&mut *self.ser)
753    }
754
755    #[inline]
756    fn serialize_value<T>(&mut self, value: &T) -> Result<()>
757    where
758        T: ?Sized + ser::Serialize,
759    {
760        value.serialize(&mut *self.ser)
761    }
762
763    #[inline]
764    fn end(self) -> Result<()> {
765        self.end_inner()
766    }
767}