spo_rhai/serde/
serialize.rs

1//! Implementations of [`serde::Serialize`].
2
3use crate::types::dynamic::Union;
4use crate::{Dynamic, ImmutableString, Scope};
5use serde::{ser::SerializeSeq, Serialize, Serializer};
6use std::iter::once;
7#[cfg(feature = "no_std")]
8use std::prelude::v1::*;
9
10#[cfg(not(feature = "no_object"))]
11use serde::ser::SerializeMap;
12
13#[cfg(not(feature = "no_time"))]
14use crate::types::dynamic::Variant;
15
16impl Serialize for Dynamic {
17    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
18        match self.0 {
19            Union::Unit(..) => ser.serialize_unit(),
20            Union::Bool(x, ..) => ser.serialize_bool(x),
21            Union::Str(ref s, ..) => ser.serialize_str(s),
22            Union::Char(c, ..) => ser.serialize_char(c),
23
24            #[cfg(not(feature = "only_i32"))]
25            Union::Int(x, ..) => ser.serialize_i64(x),
26            #[cfg(feature = "only_i32")]
27            Union::Int(x, ..) => ser.serialize_i32(x),
28
29            #[cfg(not(feature = "no_float"))]
30            #[cfg(not(feature = "f32_float"))]
31            Union::Float(x, ..) => ser.serialize_f64(*x),
32            #[cfg(not(feature = "no_float"))]
33            #[cfg(feature = "f32_float")]
34            Union::Float(x, ..) => ser.serialize_f32(*x),
35
36            #[cfg(feature = "decimal")]
37            #[cfg(not(feature = "f32_float"))]
38            Union::Decimal(ref x, ..) => {
39                use rust_decimal::prelude::ToPrimitive;
40
41                match x.to_f64() {
42                    Some(v) => ser.serialize_f64(v),
43                    None => ser.serialize_str(&x.to_string()),
44                }
45            }
46            #[cfg(feature = "decimal")]
47            #[cfg(feature = "f32_float")]
48            Union::Decimal(ref x, ..) => {
49                use rust_decimal::prelude::ToPrimitive;
50
51                match x.to_f32() {
52                    Some(v) => ser.serialize_f32(v),
53                    _ => ser.serialize_str(&x.to_string()),
54                }
55            }
56
57            #[cfg(not(feature = "no_index"))]
58            Union::Array(ref a, ..) => (**a).serialize(ser),
59            #[cfg(not(feature = "no_index"))]
60            Union::Blob(ref a, ..) => ser.serialize_bytes(a),
61            #[cfg(not(feature = "no_object"))]
62            Union::Map(ref m, ..) => {
63                let mut map = ser.serialize_map(Some(m.len()))?;
64                m.iter().try_for_each(|(k, v)| map.serialize_entry(k, v))?;
65                map.end()
66            }
67            Union::FnPtr(ref f, ..) if f.is_curried() => {
68                ser.collect_seq(once(f.fn_name().into()).chain(f.iter_curry().cloned()))
69            }
70            Union::FnPtr(ref f, ..) => ser.serialize_str(f.fn_name()),
71            #[cfg(not(feature = "no_time"))]
72            Union::TimeStamp(ref x, ..) => ser.serialize_str(x.as_ref().type_name()),
73
74            Union::Variant(ref v, ..) => ser.serialize_str((***v).type_name()),
75
76            #[cfg(not(feature = "no_closure"))]
77            #[cfg(not(feature = "sync"))]
78            Union::Shared(ref cell, ..) => cell.borrow().serialize(ser),
79            #[cfg(not(feature = "no_closure"))]
80            #[cfg(feature = "sync")]
81            Union::Shared(ref cell, ..) => cell.read().unwrap().serialize(ser),
82        }
83    }
84}
85
86impl Serialize for ImmutableString {
87    #[inline(always)]
88    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
89        ser.serialize_str(self)
90    }
91}
92
93impl Serialize for Scope<'_> {
94    #[inline(always)]
95    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
96        #[derive(Debug, Clone, Hash, Serialize)]
97        struct ScopeEntry<'a> {
98            pub name: &'a str,
99            pub value: &'a Dynamic,
100            #[serde(default, skip_serializing_if = "is_false")]
101            pub is_constant: bool,
102        }
103
104        #[allow(clippy::trivially_copy_pass_by_ref)]
105        fn is_false(value: &bool) -> bool {
106            !value
107        }
108
109        let mut ser = ser.serialize_seq(Some(self.len()))?;
110
111        for (name, is_constant, value) in self.iter_inner() {
112            let entry = ScopeEntry {
113                name,
114                value,
115                is_constant,
116            };
117            ser.serialize_element(&entry)?;
118        }
119
120        ser.end()
121    }
122}