scale_value/serde_impls/
serialize.rs

1// Copyright (C) 2022-2023 Parity Technologies (UK) Ltd. (admin@parity.io)
2// This file is a part of the scale-value crate.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//         http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16//! This [`Serialize`] impl allows [`Value`]s to be serialized to some format
17//! (eg JSON); we do our best to hand the [`Serializer`] values which most
18//! accurately represent what we've stored, but there is always some amount of
19//! converstion between our [`Value`] type and the types supported by the
20//! serde data model that we're serializing things into.
21
22use super::bitvec_helpers;
23use crate::prelude::*;
24use crate::{Composite, Primitive, Value, ValueDef, Variant};
25use serde::{
26    ser::{SerializeMap, SerializeSeq},
27    Serialize, Serializer,
28};
29
30impl<T> Serialize for Value<T> {
31    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
32    where
33        S: Serializer,
34    {
35        self.value.serialize(serializer)
36    }
37}
38
39impl<T> Serialize for ValueDef<T> {
40    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
41    where
42        S: Serializer,
43    {
44        match self {
45            ValueDef::Composite(val) => val.serialize(serializer),
46            ValueDef::Variant(val) => val.serialize(serializer),
47            ValueDef::Primitive(val) => val.serialize(serializer),
48            ValueDef::BitSequence(val) => bitvec_helpers::serialize_bitvec(val, serializer),
49        }
50    }
51}
52
53impl<T> Serialize for Composite<T> {
54    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
55    where
56        S: Serializer,
57    {
58        match self {
59            Composite::Named(vals) => {
60                let mut map = serializer.serialize_map(Some(vals.len()))?;
61                for (key, val) in vals {
62                    map.serialize_entry(key, val)?;
63                }
64                map.end()
65            }
66            Composite::Unnamed(vals) => {
67                let mut seq = serializer.serialize_seq(Some(vals.len()))?;
68                for val in vals {
69                    seq.serialize_element(val)?;
70                }
71                seq.end()
72            }
73        }
74    }
75}
76
77macro_rules! serialize_as_first_ok_type {
78    ($serializer:ident $val:ident; $first:ident $($rest:ident)*) => {{
79        let n: Result<$first,_> = $val.try_into();
80        match n {
81            Ok(n) => n.serialize($serializer),
82            Err(_) => serialize_as_first_ok_type!($serializer $val; $($rest)*)
83        }
84    }};
85    ($serializer:ident $val:ident;) => {{
86        $val.serialize($serializer)
87    }};
88}
89
90impl Serialize for Primitive {
91    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
92    where
93        S: Serializer,
94    {
95        // Delegate to the serialization strategy used by the primitive types.
96        match self {
97            Primitive::Bool(v) => v.serialize(serializer),
98            Primitive::Char(v) => v.serialize(serializer),
99            Primitive::String(v) => v.serialize(serializer),
100            Primitive::U128(v) => {
101                // Serialize into the smallest type that fits, since formats like
102                // JSON don't like u128's by default.
103                let v = *v;
104                serialize_as_first_ok_type!(serializer v; u8 u16 u32 u64 u128)
105            }
106            Primitive::U256(v) => v.serialize(serializer),
107            Primitive::I128(v) => {
108                // Serialize into the smallest type that fits, since formats like
109                // JSON don't like i128's by default.
110                let v = *v;
111                serialize_as_first_ok_type!(serializer v; i8 i16 i32 i64 i128)
112            }
113            Primitive::I256(v) => v.serialize(serializer),
114        }
115    }
116}
117
118impl<T> Serialize for Variant<T> {
119    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
120    where
121        S: Serializer,
122    {
123        // We can't use the enum serializing in the serde data model because that requires static
124        // strs and enum indexes, which we don't have (since this is a runtime value), so we serialize
125        // as a map with a type and a value, and make sure that we allow this format when attempting to
126        // deserialize into a `Variant` type for a bit of symmetry (although note that if you try to deserialize
127        // this into a `Value` type it'll have no choice but to deserialize straight into a `Composite::Named` map).
128        let mut map = serializer.serialize_map(Some(2))?;
129        map.serialize_entry("name", &self.name)?;
130        map.serialize_entry("values", &self.values)?;
131        map.end()
132    }
133}
134
135#[cfg(test)]
136mod test {
137    use crate::value;
138
139    use super::*;
140    use serde_json::json;
141
142    fn assert_value(value: Value<()>, expected: serde_json::Value) {
143        let val = serde_json::to_value(value).expect("can serialize to serde_json::Value");
144        assert_eq!(val, expected);
145    }
146
147    #[test]
148    fn serialize_primitives() {
149        // a subset of the primitives to sanity check that they are unwrapped:
150        assert_value(Value::u128(1), json!(1));
151        assert_value(Value::bool(true), json!(true));
152        assert_value(Value::bool(false), json!(false));
153    }
154
155    #[test]
156    fn serialize_composites() {
157        assert_value(
158            value!({
159                a: true,
160                b: "hello",
161                c: 'c'
162            }),
163            json!({
164                "a": true,
165                "b": "hello",
166                "c": 'c'
167            }),
168        );
169        assert_value(value!((true, "hello", 'c')), json!([true, "hello", 'c']))
170    }
171
172    #[test]
173    fn serialize_variants() {
174        assert_value(
175            value!(Foo { a: true, b: "hello", c: 'c' }),
176            json!({
177                "name": "Foo",
178                "values": {
179                    "a": true,
180                    "b": "hello",
181                    "c": 'c'
182                }
183            }),
184        );
185        assert_value(
186            value!(Bar(true, "hello", 'c')),
187            json!({
188                "name": "Bar",
189                "values": [
190                    true,
191                    "hello",
192                    'c'
193                ]
194            }),
195        )
196    }
197
198    #[test]
199    fn serialize_bitsequences() {
200        use scale_bits::bits;
201
202        assert_value(
203            Value::bit_sequence(bits![]),
204            json!({
205                "__bitvec__values__": []
206            }),
207        );
208        assert_value(
209            Value::bit_sequence(bits![0, 1, 1, 0, 1]),
210            json!({
211                "__bitvec__values__": [false, true, true, false, true]
212            }),
213        );
214    }
215}