core_serde_json/ser/
mod.rs

1//! Serialize a Rust data structure into JSON data
2
3use core::{fmt, mem};
4
5use serde::ser;
6
7use heapless::{String, Vec};
8
9use self::seq::SerializeSeq;
10use self::struct_::SerializeStruct;
11
12mod seq;
13mod struct_;
14
15/// Serialization result
16pub type Result<T> = ::core::result::Result<T, Error>;
17
18/// This type represents all possible errors that can occur when serializing JSON data
19#[derive(Debug)]
20pub enum Error {
21    /// Buffer is full
22    BufferFull,
23    #[doc(hidden)]
24    __Extensible,
25}
26
27impl From<()> for Error {
28    fn from(_: ()) -> Error {
29        Error::BufferFull
30    }
31}
32
33impl From<u8> for Error {
34    fn from(_: u8) -> Error {
35        Error::BufferFull
36    }
37}
38
39#[cfg(feature = "std")]
40impl ::std::error::Error for Error {
41    fn description(&self) -> &str {
42        ""
43    }
44}
45
46impl fmt::Display for Error {
47    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48        write!(f, "Buffer is full")
49    }
50}
51
52pub(crate) struct Serializer<B>
53where
54    B: heapless::ArrayLength<u8>,
55{
56    buf: Vec<u8, B>,
57}
58
59impl<B> Serializer<B>
60where
61    B: heapless::ArrayLength<u8>,
62{
63    fn new() -> Self {
64        Serializer { buf: Vec::new() }
65    }
66}
67
68// NOTE(serialize_*signed) This is basically the numtoa implementation minus the lookup tables,
69// which take 200+ bytes of ROM / Flash
70macro_rules! serialize_unsigned {
71    ($self:ident, $N:expr, $v:expr) => {{
72        let mut buf: [u8; $N] = unsafe { mem::MaybeUninit::uninit().assume_init() };
73
74        let mut v = $v;
75        let mut i = $N - 1;
76        loop {
77            buf[i] = (v % 10) as u8 + b'0';
78            v /= 10;
79
80            if v == 0 {
81                break;
82            } else {
83                i -= 1;
84            }
85        }
86
87        $self.buf.extend_from_slice(&buf[i..])?;
88        Ok(())
89    }};
90}
91
92macro_rules! serialize_signed {
93    ($self:ident, $N:expr, $v:expr, $ixx:ident, $uxx:ident) => {{
94        let v = $v;
95        let (signed, mut v) = if v == $ixx::min_value() {
96            (true, $ixx::max_value() as $uxx + 1)
97        } else if v < 0 {
98            (true, -v as $uxx)
99        } else {
100            (false, v as $uxx)
101        };
102
103        let mut buf: [u8; $N] = unsafe { mem::MaybeUninit::uninit().assume_init() };
104        let mut i = $N - 1;
105        loop {
106            buf[i] = (v % 10) as u8 + b'0';
107            v /= 10;
108
109            i -= 1;
110
111            if v == 0 {
112                break;
113            }
114        }
115
116        if signed {
117            buf[i] = b'-';
118        } else {
119            i += 1;
120        }
121        $self.buf.extend_from_slice(&buf[i..])?;
122        Ok(())
123    }};
124}
125
126impl<'a, B> ser::Serializer for &'a mut Serializer<B>
127where
128    B: heapless::ArrayLength<u8>,
129{
130    type Ok = ();
131    type Error = Error;
132    type SerializeSeq = SerializeSeq<'a, B>;
133    type SerializeTuple = SerializeSeq<'a, B>;
134    type SerializeTupleStruct = Unreachable;
135    type SerializeTupleVariant = Unreachable;
136    type SerializeMap = Unreachable;
137    type SerializeStruct = SerializeStruct<'a, B>;
138    type SerializeStructVariant = Unreachable;
139
140    fn serialize_bool(self, v: bool) -> Result<Self::Ok> {
141        if v {
142            self.buf.extend_from_slice(b"true")?;
143        } else {
144            self.buf.extend_from_slice(b"false")?;
145        }
146
147        Ok(())
148    }
149
150    fn serialize_i8(self, v: i8) -> Result<Self::Ok> {
151        // "-128"
152        serialize_signed!(self, 4, v, i8, u8)
153    }
154
155    fn serialize_i16(self, v: i16) -> Result<Self::Ok> {
156        // "-32768"
157        serialize_signed!(self, 6, v, i16, u16)
158    }
159
160    fn serialize_i32(self, v: i32) -> Result<Self::Ok> {
161        // "-2147483648"
162        serialize_signed!(self, 11, v, i32, u32)
163    }
164
165    fn serialize_i64(self, v: i64) -> Result<Self::Ok> {
166        // "-9223372036854775808"
167        serialize_signed!(self, 20, v, i64, u64)
168    }
169
170    fn serialize_u8(self, v: u8) -> Result<Self::Ok> {
171        // "255"
172        serialize_unsigned!(self, 3, v)
173    }
174
175    fn serialize_u16(self, v: u16) -> Result<Self::Ok> {
176        // "65535"
177        serialize_unsigned!(self, 5, v)
178    }
179
180    fn serialize_u32(self, v: u32) -> Result<Self::Ok> {
181        // "4294967295"
182        serialize_unsigned!(self, 10, v)
183    }
184
185    fn serialize_u64(self, v: u64) -> Result<Self::Ok> {
186        // "18446744073709551615"
187        serialize_unsigned!(self, 20, v)
188    }
189
190    fn serialize_f32(self, _v: f32) -> Result<Self::Ok> {
191        unreachable!()
192    }
193
194    fn serialize_f64(self, _v: f64) -> Result<Self::Ok> {
195        unreachable!()
196    }
197
198    fn serialize_char(self, _v: char) -> Result<Self::Ok> {
199        unreachable!()
200    }
201
202    fn serialize_str(self, v: &str) -> Result<Self::Ok> {
203        self.buf.push(b'"')?;
204        self.buf.extend_from_slice(v.as_bytes())?;
205        self.buf.push(b'"')?;
206        Ok(())
207    }
208
209    fn serialize_bytes(self, _v: &[u8]) -> Result<Self::Ok> {
210        unreachable!()
211    }
212
213    fn serialize_none(self) -> Result<Self::Ok> {
214        self.buf.extend_from_slice(b"null")?;
215        Ok(())
216    }
217
218    fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok>
219    where
220        T: ser::Serialize,
221    {
222        value.serialize(self)
223    }
224
225    fn serialize_unit(self) -> Result<Self::Ok> {
226        unreachable!()
227    }
228
229    fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok> {
230        unreachable!()
231    }
232
233    fn serialize_unit_variant(
234        self,
235        _name: &'static str,
236        _variant_index: u32,
237        variant: &'static str,
238    ) -> Result<Self::Ok> {
239        self.serialize_str(variant)
240    }
241
242    fn serialize_newtype_struct<T: ?Sized>(
243        self,
244        _name: &'static str,
245        _value: &T,
246    ) -> Result<Self::Ok>
247    where
248        T: ser::Serialize,
249    {
250        unreachable!()
251    }
252
253    fn serialize_newtype_variant<T: ?Sized>(
254        self,
255        _name: &'static str,
256        _variant_index: u32,
257        _variant: &'static str,
258        _value: &T,
259    ) -> Result<Self::Ok>
260    where
261        T: ser::Serialize,
262    {
263        unreachable!()
264    }
265
266    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
267        self.buf.push(b'[')?;
268
269        Ok(SerializeSeq::new(self))
270    }
271
272    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
273        self.serialize_seq(Some(_len))
274    }
275
276    fn serialize_tuple_struct(
277        self,
278        _name: &'static str,
279        _len: usize,
280    ) -> Result<Self::SerializeTupleStruct> {
281        unreachable!()
282    }
283
284    fn serialize_tuple_variant(
285        self,
286        _name: &'static str,
287        _variant_index: u32,
288        _variant: &'static str,
289        _len: usize,
290    ) -> Result<Self::SerializeTupleVariant> {
291        unreachable!()
292    }
293
294    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
295        unreachable!()
296    }
297
298    fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
299        self.buf.push(b'{')?;
300
301        Ok(SerializeStruct::new(self))
302    }
303
304    fn serialize_struct_variant(
305        self,
306        _name: &'static str,
307        _variant_index: u32,
308        _variant: &'static str,
309        _len: usize,
310    ) -> Result<Self::SerializeStructVariant> {
311        unreachable!()
312    }
313
314    fn collect_str<T: ?Sized>(self, _value: &T) -> Result<Self::Ok>
315    where
316        T: fmt::Display,
317    {
318        unreachable!()
319    }
320}
321
322/// Serializes the given data structure as a string of JSON text
323pub fn to_string<B, T>(value: &T) -> Result<String<B>>
324where
325    B: heapless::ArrayLength<u8>,
326    T: ser::Serialize + ?Sized,
327{
328    let mut ser = Serializer::new();
329    value.serialize(&mut ser)?;
330    Ok(unsafe { String::from_utf8_unchecked(ser.buf) })
331}
332
333/// Serializes the given data structure as a JSON byte vector
334pub fn to_vec<B, T>(value: &T) -> Result<Vec<u8, B>>
335where
336    B: heapless::ArrayLength<u8>,
337    T: ser::Serialize + ?Sized,
338{
339    let mut ser = Serializer::new();
340    value.serialize(&mut ser)?;
341    Ok(ser.buf)
342}
343
344impl ser::Error for Error {
345    fn custom<T>(_msg: T) -> Self
346    where
347        T: fmt::Display,
348    {
349        unreachable!()
350    }
351}
352
353pub(crate) enum Unreachable {}
354
355impl ser::SerializeTupleStruct for Unreachable {
356    type Ok = ();
357    type Error = Error;
358
359    fn serialize_field<T: ?Sized>(&mut self, _value: &T) -> Result<()> {
360        unreachable!()
361    }
362
363    fn end(self) -> Result<Self::Ok> {
364        unreachable!()
365    }
366}
367
368impl ser::SerializeTupleVariant for Unreachable {
369    type Ok = ();
370    type Error = Error;
371
372    fn serialize_field<T: ?Sized>(&mut self, _value: &T) -> Result<()> {
373        unreachable!()
374    }
375
376    fn end(self) -> Result<Self::Ok> {
377        unreachable!()
378    }
379}
380
381impl ser::SerializeMap for Unreachable {
382    type Ok = ();
383    type Error = Error;
384
385    fn serialize_key<T: ?Sized>(&mut self, _key: &T) -> Result<()>
386    where
387        T: ser::Serialize,
388    {
389        unreachable!()
390    }
391
392    fn serialize_value<T: ?Sized>(&mut self, _value: &T) -> Result<()>
393    where
394        T: ser::Serialize,
395    {
396        unreachable!()
397    }
398
399    fn end(self) -> Result<Self::Ok> {
400        unreachable!()
401    }
402}
403
404impl ser::SerializeStructVariant for Unreachable {
405    type Ok = ();
406    type Error = Error;
407
408    fn serialize_field<T: ?Sized>(&mut self, _key: &'static str, _value: &T) -> Result<()>
409    where
410        T: ser::Serialize,
411    {
412        unreachable!()
413    }
414
415    fn end(self) -> Result<Self::Ok> {
416        unreachable!()
417    }
418}
419
420#[cfg(test)]
421mod tests {
422    use serde_derive::Serialize;
423
424    use heapless::consts::U128;
425
426    type N = U128;
427
428    #[test]
429    fn array() {
430        assert_eq!(&*crate::to_string::<N, _>(&[0, 1, 2]).unwrap(), "[0,1,2]");
431    }
432
433    #[test]
434    fn bool() {
435        assert_eq!(&*crate::to_string::<N, _>(&true).unwrap(), "true");
436    }
437
438    #[test]
439    fn enum_() {
440        #[derive(Serialize)]
441        enum Type {
442            #[serde(rename = "boolean")]
443            Boolean,
444            #[serde(rename = "number")]
445            Number,
446        }
447
448        assert_eq!(
449            &*crate::to_string::<N, _>(&Type::Boolean).unwrap(),
450            r#""boolean""#
451        );
452
453        assert_eq!(
454            &*crate::to_string::<N, _>(&Type::Number).unwrap(),
455            r#""number""#
456        );
457    }
458
459    #[test]
460    fn str() {
461        assert_eq!(&*crate::to_string::<N, _>("hello").unwrap(), r#""hello""#);
462    }
463
464    #[test]
465    fn struct_bool() {
466        #[derive(Serialize)]
467        struct Led {
468            led: bool,
469        }
470
471        assert_eq!(
472            &*crate::to_string::<N, _>(&Led { led: true }).unwrap(),
473            r#"{"led":true}"#
474        );
475    }
476
477    #[test]
478    fn struct_i8() {
479        #[derive(Serialize)]
480        struct Temperature {
481            temperature: i8,
482        }
483
484        assert_eq!(
485            &*crate::to_string::<N, _>(&Temperature { temperature: 127 }).unwrap(),
486            r#"{"temperature":127}"#
487        );
488
489        assert_eq!(
490            &*crate::to_string::<N, _>(&Temperature { temperature: 20 }).unwrap(),
491            r#"{"temperature":20}"#
492        );
493
494        assert_eq!(
495            &*crate::to_string::<N, _>(&Temperature { temperature: -17 }).unwrap(),
496            r#"{"temperature":-17}"#
497        );
498
499        assert_eq!(
500            &*crate::to_string::<N, _>(&Temperature { temperature: -128 }).unwrap(),
501            r#"{"temperature":-128}"#
502        );
503    }
504
505    #[test]
506    fn struct_option() {
507        #[derive(Serialize)]
508        struct Property<'a> {
509            description: Option<&'a str>,
510        }
511
512        assert_eq!(
513            crate::to_string::<N, _>(&Property {
514                description: Some("An ambient temperature sensor"),
515            })
516            .unwrap(),
517            r#"{"description":"An ambient temperature sensor"}"#
518        );
519
520        // XXX Ideally this should produce "{}"
521        assert_eq!(
522            crate::to_string::<N, _>(&Property { description: None }).unwrap(),
523            r#"{"description":null}"#
524        );
525    }
526
527    #[test]
528    fn struct_u8() {
529        #[derive(Serialize)]
530        struct Temperature {
531            temperature: u8,
532        }
533
534        assert_eq!(
535            &*crate::to_string::<N, _>(&Temperature { temperature: 20 }).unwrap(),
536            r#"{"temperature":20}"#
537        );
538    }
539
540    #[test]
541    fn struct_() {
542        #[derive(Serialize)]
543        struct Empty {}
544
545        assert_eq!(&*crate::to_string::<N, _>(&Empty {}).unwrap(), r#"{}"#);
546
547        #[derive(Serialize)]
548        struct Tuple {
549            a: bool,
550            b: bool,
551        }
552
553        assert_eq!(
554            &*crate::to_string::<N, _>(&Tuple { a: true, b: false }).unwrap(),
555            r#"{"a":true,"b":false}"#
556        );
557    }
558}