spo_rhai/serde/
serialize.rs1use 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}