ssb_json_msg_data/json/
ser.rs

1use std::{error, fmt, io};
2
3use base64;
4use ryu_ecmascript;
5use serde::ser::{
6    self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
7    SerializeTuple, SerializeTupleStruct, SerializeTupleVariant, Serializer,
8};
9
10use super::super::{is_i64_valid, is_u64_valid, LegacyF64};
11
12/// Everything that can go wrong during json serialization.
13#[derive(Debug)]
14pub enum EncodeJsonError {
15    /// An IO error occured on the underlying writer.
16    ///
17    /// When serializing directly into a `Vec<u8>` or `String`, this error never occurs.
18    Io(io::Error),
19    /// Tried to serialize a number forbidden by the ssb data format (an inifinity, NaN or -0.0).
20    InvalidFloat(f64),
21    /// Tried to serialize an unsigned integer larger than 2^53 (these are not
22    /// guaranteed to be represented correctly in a 64 bit float).
23    InvalidUnsignedInteger(u64),
24    /// Tried to serialize an signed integer with absolute value larger than 2^53 (these are not
25    /// guaranteed to be represented correctly in a 64 bit float).
26    InvalidSignedInteger(i64),
27    /// Can only serialize collections whose length is known upfront.
28    UnknownLength,
29    /// Custom, stringly-typed error.
30    Message(String),
31}
32
33impl fmt::Display for EncodeJsonError {
34    fn fmt(&self, f: &mut fmt::Formatter) -> std::result::Result<(), fmt::Error> {
35        fmt::Debug::fmt(self, f)
36    }
37}
38
39impl error::Error for EncodeJsonError {}
40
41impl ser::Error for EncodeJsonError {
42    fn custom<T: fmt::Display>(msg: T) -> Self {
43        EncodeJsonError::Message(msg.to_string())
44    }
45}
46
47impl From<io::Error> for EncodeJsonError {
48    fn from(e: io::Error) -> Self {
49        EncodeJsonError::Io(e)
50    }
51}
52
53/// A structure for serializing data into the legacy json encoding.
54pub struct JsonSerializer<W> {
55    writer: W,
56    // If true omits whitespace, else produces the signing format.
57    compact: bool,
58    indent: usize,
59}
60
61impl<W> JsonSerializer<W>
62where
63    W: io::Write,
64{
65    /// Creates a new serializer.
66    ///
67    /// If `compact`, this omits all whitespace. For signing or signature checking,
68    /// set `compact` to `false`.
69    ///
70    /// If `compact` is `true`, then `indent` is used as the starting indentation level.
71    #[inline]
72    pub fn new(writer: W, compact: bool, indent: usize) -> Self {
73        JsonSerializer {
74            writer,
75            compact,
76            indent,
77        }
78    }
79
80    /// Unwrap the `Writer` from the `Serializer`.
81    pub fn into_inner(self) -> W {
82        self.writer
83    }
84
85    // Writes the correct number of spaces as indentation.
86    fn write_indent(&mut self) -> Result<(), io::Error> {
87        for _ in 0..self.indent {
88            self.writer.write_all(b"  ")?;
89        }
90        Ok(())
91    }
92
93    fn begin_object(&mut self) -> Result<(), io::Error> {
94        self.writer.write_all(b"{")?;
95        self.indent += 1;
96        Ok(())
97    }
98
99    fn end_object(&mut self) -> Result<(), io::Error> {
100        self.writer.write_all(b"}")?;
101        self.indent -= 1;
102        Ok(())
103    }
104
105    fn begin_array(&mut self) -> Result<(), io::Error> {
106        self.writer.write_all(b"[")?;
107        self.indent += 1;
108        Ok(())
109    }
110
111    fn colon(&mut self) -> Result<(), io::Error> {
112        self.writer.write_all(b":")?;
113
114        if !self.compact {
115            self.writer.write_all(b" ")?;
116        }
117
118        Ok(())
119    }
120
121    fn newline(&mut self) -> Result<(), io::Error> {
122        if !self.compact {
123            self.writer.write_all(b"\n")?;
124            self.write_indent()?;
125        }
126        Ok(())
127    }
128}
129
130/// Serialize the given data structure as JSON into the IO stream.
131pub fn to_writer<W, T: ?Sized>(
132    writer: &mut W,
133    value: &T,
134    compact: bool,
135) -> Result<(), EncodeJsonError>
136where
137    W: io::Write,
138    T: Serialize,
139{
140    let mut ser = JsonSerializer::new(writer, compact, 0);
141    value.serialize(&mut ser)
142}
143
144/// Serialize the given data structure as JSON into the IO stream.
145pub fn to_writer_indent<W, T: ?Sized>(
146    writer: &mut W,
147    value: &T,
148    compact: bool,
149    indent: usize,
150) -> Result<(), EncodeJsonError>
151where
152    W: io::Write,
153    T: Serialize,
154{
155    let mut ser = JsonSerializer::new(writer, compact, indent);
156    value.serialize(&mut ser)
157}
158
159/// Serialize the given data structure  as JSON into a JSON byte vector.
160pub fn to_vec<T: ?Sized>(value: &T, compact: bool) -> Result<Vec<u8>, EncodeJsonError>
161where
162    T: Serialize,
163{
164    let mut writer = Vec::with_capacity(128);
165    to_writer(&mut writer, value, compact).map(|_| writer)
166}
167
168/// Serialize the given data structure as JSON into a `String`.
169pub fn to_string<T: ?Sized>(value: &T, compact: bool) -> Result<String, EncodeJsonError>
170where
171    T: Serialize,
172{
173    to_vec(value, compact).map(|bytes| unsafe {
174        // We do not emit invalid UTF-8.
175        String::from_utf8_unchecked(bytes)
176    })
177}
178
179impl<'a, W> Serializer for &'a mut JsonSerializer<W>
180where
181    W: io::Write,
182{
183    type Ok = ();
184    type Error = EncodeJsonError;
185
186    type SerializeSeq = CollectionSerializer<'a, W>;
187    type SerializeTuple = CollectionSerializer<'a, W>;
188    type SerializeTupleStruct = CollectionSerializer<'a, W>;
189    type SerializeTupleVariant = CollectionSerializer<'a, W>;
190    type SerializeMap = CollectionSerializer<'a, W>;
191    type SerializeStruct = CollectionSerializer<'a, W>;
192    type SerializeStructVariant = CollectionSerializer<'a, W>;
193
194    fn is_human_readable(&self) -> bool {
195        true
196    }
197
198    // https://spec.scuttlebutt.nz/datamodel.html#signing-encoding-booleans
199    fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
200        let s = if v {
201            b"true" as &[u8]
202        } else {
203            b"false" as &[u8]
204        };
205        Ok(self.writer.write_all(s)?)
206    }
207
208    fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
209        self.serialize_i64(v as i64)
210    }
211
212    fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
213        self.serialize_i64(v as i64)
214    }
215
216    fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
217        self.serialize_i64(v as i64)
218    }
219
220    fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
221        if is_i64_valid(v) {
222            self.serialize_f64(v as f64)
223        } else {
224            Err(EncodeJsonError::InvalidSignedInteger(v))
225        }
226    }
227
228    fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
229        self.serialize_u64(v as u64)
230    }
231
232    fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
233        self.serialize_u64(v as u64)
234    }
235
236    fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
237        self.serialize_u64(v as u64)
238    }
239
240    fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
241        if is_u64_valid(v) {
242            self.serialize_f64(v as f64)
243        } else {
244            Err(EncodeJsonError::InvalidUnsignedInteger(v))
245        }
246    }
247
248    fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
249        self.serialize_f64(v as f64)
250    }
251
252    // https://spec.scuttlebutt.nz/datamodel.html#signing-encoding-floats
253    fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
254        if LegacyF64::is_valid(v) {
255            let mut buffer = ryu_ecmascript::Buffer::new();
256            let s = buffer.format::<f64>(v.into());
257            Ok(self.writer.write_all(s.as_bytes())?)
258        } else {
259            Err(EncodeJsonError::InvalidFloat(v))
260        }
261    }
262
263    fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
264        self.serialize_str(&v.to_string())
265    }
266
267    // https://spec.scuttlebutt.nz/datamodel.html#signing-encoding-strings
268    fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
269        self.writer.write_all(b"\"")?;
270
271        for byte in v.bytes() {
272            match byte {
273                0x00 => self.writer.write_all(br"\u0000")?,
274                0x01 => self.writer.write_all(br"\u0001")?,
275                0x02 => self.writer.write_all(br"\u0002")?,
276                0x03 => self.writer.write_all(br"\u0003")?,
277                0x04 => self.writer.write_all(br"\u0004")?,
278                0x05 => self.writer.write_all(br"\u0005")?,
279                0x06 => self.writer.write_all(br"\u0006")?,
280                0x07 => self.writer.write_all(br"\u0007")?,
281                0x08 => self.writer.write_all(br"\b")?,
282                0x09 => self.writer.write_all(br"\t")?,
283                0x0A => self.writer.write_all(br"\n")?,
284                0x0B => self.writer.write_all(br"\u000b")?,
285                0x0C => self.writer.write_all(br"\f")?,
286                0x0D => self.writer.write_all(br"\r")?,
287                0x0E => self.writer.write_all(br"\u000e")?,
288                0x0F => self.writer.write_all(br"\u000f")?,
289                0x10 => self.writer.write_all(br"\u0010")?,
290                0x11 => self.writer.write_all(br"\u0011")?,
291                0x12 => self.writer.write_all(br"\u0012")?,
292                0x13 => self.writer.write_all(br"\u0013")?,
293                0x14 => self.writer.write_all(br"\u0014")?,
294                0x15 => self.writer.write_all(br"\u0015")?,
295                0x16 => self.writer.write_all(br"\u0016")?,
296                0x17 => self.writer.write_all(br"\u0017")?,
297                0x18 => self.writer.write_all(br"\u0018")?,
298                0x19 => self.writer.write_all(br"\u0019")?,
299                0x1A => self.writer.write_all(br"\u001a")?,
300                0x1B => self.writer.write_all(br"\u001b")?,
301                0x1C => self.writer.write_all(br"\u001c")?,
302                0x1D => self.writer.write_all(br"\u001d")?,
303                0x1E => self.writer.write_all(br"\u001e")?,
304                0x1F => self.writer.write_all(br"\u001f")?,
305                0x22 => self.writer.write_all(b"\\\"")?,
306                0x5C => self.writer.write_all(br"\\")?,
307                other => self.writer.write_all(&[other])?,
308            }
309        }
310
311        self.writer.write_all(b"\"").map_err(EncodeJsonError::Io)
312    }
313
314    // Serializing as base64.
315    //
316    // This not mandated by the spec in any way. From the spec's perspective, this
317    // outputs a string like any other.
318    fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
319        self.serialize_str(&base64::encode(v))
320    }
321
322    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
323        self.serialize_unit()
324    }
325
326    fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
327    where
328        T: ?Sized + Serialize,
329    {
330        value.serialize(self)
331    }
332
333    // https://spec.scuttlebutt.nz/datamodel.html#signing-encoding-null
334    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
335        Ok(self.writer.write_all(b"null")?)
336    }
337
338    fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
339        self.serialize_unit()
340    }
341
342    fn serialize_unit_variant(
343        self,
344        _name: &'static str,
345        _variant_index: u32,
346        variant: &'static str,
347    ) -> Result<Self::Ok, Self::Error> {
348        self.serialize_str(variant)
349    }
350
351    fn serialize_newtype_struct<T>(
352        self,
353        _name: &'static str,
354        value: &T,
355    ) -> Result<Self::Ok, Self::Error>
356    where
357        T: ?Sized + Serialize,
358    {
359        value.serialize(self)
360    }
361
362    // https://spec.scuttlebutt.nz/datamodel.html#signing-encoding-objects
363    fn serialize_newtype_variant<T: ?Sized>(
364        self,
365        _name: &'static str,
366        _variant_index: u32,
367        variant: &'static str,
368        value: &T,
369    ) -> Result<Self::Ok, Self::Error>
370    where
371        T: Serialize,
372    {
373        self.begin_object()?;
374        self.newline()?;
375
376        variant.serialize(&mut *self)?;
377        self.colon()?;
378        value.serialize(&mut *self)?;
379
380        self.newline()?;
381        self.end_object()?;
382        Ok(())
383    }
384
385    // https://spec.scuttlebutt.nz/datamodel.html#signing-encoding-arrays
386    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, EncodeJsonError> {
387        match _len {
388            None => return Err(EncodeJsonError::UnknownLength),
389            Some(len) => {
390                self.begin_array()?;
391                Ok(CollectionSerializer::new(&mut *self, len == 0))
392            }
393        }
394    }
395
396    fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, EncodeJsonError> {
397        self.serialize_seq(Some(len))
398    }
399
400    fn serialize_tuple_struct(
401        self,
402        _name: &'static str,
403        len: usize,
404    ) -> Result<Self::SerializeTupleStruct, EncodeJsonError> {
405        self.serialize_seq(Some(len))
406    }
407
408    // https://spec.scuttlebutt.nz/datamodel.html#signing-encoding-objects
409    // https://spec.scuttlebutt.nz/datamodel.html#signing-encoding-arrays
410    fn serialize_tuple_variant(
411        self,
412        _name: &'static str,
413        _variant_index: u32,
414        variant: &'static str,
415        _len: usize,
416    ) -> Result<Self::SerializeTupleVariant, EncodeJsonError> {
417        self.begin_object()?;
418        self.newline()?;
419
420        variant.serialize(&mut *self)?;
421        self.colon()?;
422        self.begin_array()?;
423
424        Ok(CollectionSerializer::new(&mut *self, false))
425    }
426
427    // https://spec.scuttlebutt.nz/datamodel.html#signing-encoding-objects
428    fn serialize_map(self, len_: Option<usize>) -> Result<Self::SerializeMap, EncodeJsonError> {
429        match len_ {
430            None => return Err(EncodeJsonError::UnknownLength),
431            Some(len) => {
432                self.begin_object()?;
433                Ok(CollectionSerializer::new(&mut *self, len == 0))
434            }
435        }
436    }
437
438    fn serialize_struct(
439        self,
440        _name: &'static str,
441        len: usize,
442    ) -> Result<Self::SerializeStruct, EncodeJsonError> {
443        self.serialize_map(Some(len))
444    }
445
446    // https://spec.scuttlebutt.nz/datamodel.html#signing-encoding-objects
447    fn serialize_struct_variant(
448        self,
449        _name: &'static str,
450        _variant_index: u32,
451        variant: &'static str,
452        _len: usize,
453    ) -> Result<Self::SerializeStructVariant, EncodeJsonError> {
454        self.begin_object()?;
455        self.newline()?;
456
457        variant.serialize(&mut *self)?;
458        self.colon()?;
459        self.begin_object()?;
460
461        Ok(CollectionSerializer::new(&mut *self, false))
462    }
463}
464
465#[doc(hidden)]
466pub struct CollectionSerializer<'a, W> {
467    ser: &'a mut JsonSerializer<W>,
468    first: bool,
469    empty: bool,
470}
471
472impl<'a, W: io::Write> CollectionSerializer<'a, W> {
473    fn new(ser: &'a mut JsonSerializer<W>, empty: bool) -> CollectionSerializer<'a, W> {
474        CollectionSerializer {
475            ser,
476            first: true,
477            empty,
478        }
479    }
480
481    fn comma(&mut self) -> Result<(), io::Error> {
482        if self.first {
483            self.first = false;
484        } else {
485            self.ser.writer.write_all(b",")?;
486        }
487
488        self.ser.newline()
489    }
490
491    fn end_array(&mut self) -> Result<(), io::Error> {
492        self.ser.indent -= 1;
493        if !self.empty {
494            self.ser.newline()?;
495        }
496        self.ser.writer.write_all(b"]")
497    }
498
499    fn end_object(&mut self) -> Result<(), io::Error> {
500        self.ser.indent -= 1;
501        if !self.empty {
502            self.ser.newline()?;
503        }
504        self.ser.writer.write_all(b"}")
505    }
506}
507
508impl<'a, W> SerializeSeq for CollectionSerializer<'a, W>
509where
510    W: io::Write,
511{
512    type Ok = ();
513    type Error = EncodeJsonError;
514
515    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
516    where
517        T: Serialize,
518    {
519        self.comma()?;
520        value.serialize(&mut *self.ser)?;
521        Ok(())
522    }
523
524    fn end(mut self) -> Result<Self::Ok, Self::Error> {
525        self.end_array()?;
526        Ok(())
527    }
528}
529
530impl<'a, W> SerializeTuple for CollectionSerializer<'a, W>
531where
532    W: io::Write,
533{
534    type Ok = ();
535    type Error = EncodeJsonError;
536
537    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
538    where
539        T: Serialize,
540    {
541        SerializeSeq::serialize_element(self, value)
542    }
543
544    fn end(self) -> Result<Self::Ok, Self::Error> {
545        SerializeSeq::end(self)
546    }
547}
548
549impl<'a, W> SerializeTupleStruct for CollectionSerializer<'a, W>
550where
551    W: io::Write,
552{
553    type Ok = ();
554    type Error = EncodeJsonError;
555
556    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
557    where
558        T: Serialize,
559    {
560        SerializeSeq::serialize_element(self, value)
561    }
562
563    fn end(self) -> Result<Self::Ok, Self::Error> {
564        SerializeSeq::end(self)
565    }
566}
567
568impl<'a, W> SerializeTupleVariant for CollectionSerializer<'a, W>
569where
570    W: io::Write,
571{
572    type Ok = ();
573    type Error = EncodeJsonError;
574
575    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
576    where
577        T: Serialize,
578    {
579        SerializeSeq::serialize_element(self, value)
580    }
581
582    fn end(mut self) -> Result<Self::Ok, Self::Error> {
583        self.end_array()?;
584        self.end_object()?;
585        Ok(())
586    }
587}
588
589impl<'a, W> SerializeMap for CollectionSerializer<'a, W>
590where
591    W: io::Write,
592{
593    type Ok = ();
594    type Error = EncodeJsonError;
595
596    fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
597    where
598        T: Serialize,
599    {
600        self.comma()?;
601        key.serialize(&mut *self.ser)?;
602        self.ser.colon()?;
603        Ok(())
604    }
605
606    fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
607    where
608        T: Serialize,
609    {
610        value.serialize(&mut *self.ser)?;
611        Ok(())
612    }
613
614    fn end(mut self) -> Result<Self::Ok, Self::Error> {
615        self.end_object()?;
616        Ok(())
617    }
618}
619
620impl<'a, W> SerializeStruct for CollectionSerializer<'a, W>
621where
622    W: io::Write,
623{
624    type Ok = ();
625    type Error = EncodeJsonError;
626
627    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), EncodeJsonError>
628    where
629        T: ?Sized + Serialize,
630    {
631        SerializeMap::serialize_entry(self, key, value)
632    }
633
634    fn end(self) -> Result<(), EncodeJsonError> {
635        SerializeMap::end(self)
636    }
637}
638
639impl<'a, W> SerializeStructVariant for CollectionSerializer<'a, W>
640where
641    W: io::Write,
642{
643    type Ok = ();
644    type Error = EncodeJsonError;
645
646    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), EncodeJsonError>
647    where
648        T: ?Sized + Serialize,
649    {
650        SerializeMap::serialize_entry(self, key, value)
651    }
652
653    fn end(mut self) -> Result<Self::Ok, Self::Error> {
654        self.end_object()?;
655        self.end_object()?;
656        Ok(())
657    }
658}