simd_json/value/owned/
serialize.rs

1// This is mostly taken from json-rust's codegen
2// as it seems to perform well and it makes sense to see
3// if we can adopt the approach
4//
5// https://github.com/maciejhirsz/json-rust/blob/master/src/codegen.rs
6
7use super::{Object, Value};
8use crate::prelude::*;
9use std::io;
10use std::io::Write;
11use value_trait::generator::{
12    DumpGenerator, PrettyGenerator, PrettyWriterGenerator, WriterGenerator,
13};
14
15//use util::print_dec;
16
17impl Writable for Value {
18    #[cfg_attr(not(feature = "no-inline"), inline)]
19    fn encode(&self) -> String {
20        let mut g = DumpGenerator::new();
21        let _r = g.write_json(self);
22        g.consume()
23    }
24
25    #[cfg_attr(not(feature = "no-inline"), inline)]
26    fn encode_pp(&self) -> String {
27        let mut g = PrettyGenerator::new(2);
28        let _r = g.write_json(self);
29        g.consume()
30    }
31
32    #[cfg_attr(not(feature = "no-inline"), inline)]
33    fn write<'writer, W>(&self, w: &mut W) -> io::Result<()>
34    where
35        W: 'writer + Write,
36    {
37        let mut g = WriterGenerator::new(w);
38        g.write_json(self)
39    }
40
41    #[cfg_attr(not(feature = "no-inline"), inline)]
42    fn write_pp<'writer, W>(&self, w: &mut W) -> io::Result<()>
43    where
44        W: 'writer + Write,
45    {
46        let mut g = PrettyWriterGenerator::new(w, 2);
47        g.write_json(self)
48    }
49}
50
51trait Generator: BaseGenerator {
52    type T: Write;
53
54    #[cfg_attr(not(feature = "no-inline"), inline)]
55    fn write_object(&mut self, object: &Object) -> io::Result<()> {
56        if object.is_empty() {
57            self.write(b"{}")
58        } else {
59            let mut iter = object.iter();
60            stry!(self.write(b"{"));
61
62            // We know this exists since it's not empty
63            let (key, value) = if let Some(v) = iter.next() {
64                v
65            } else {
66                // We check against size
67                unreachable!();
68            };
69            self.indent();
70            stry!(self.new_line());
71            stry!(self.write_simple_string(key));
72            stry!(self.write_min(b": ", b':'));
73            stry!(self.write_json(value));
74
75            for (key, value) in iter {
76                stry!(self.write(b","));
77                stry!(self.new_line());
78                stry!(self.write_simple_string(key));
79                stry!(self.write_min(b": ", b':'));
80                stry!(self.write_json(value));
81            }
82            self.dedent();
83            stry!(self.new_line());
84            self.write(b"}")
85        }
86    }
87
88    #[cfg_attr(not(feature = "no-inline"), inline)]
89    fn write_json(&mut self, json: &Value) -> io::Result<()> {
90        match *json {
91            Value::Static(StaticNode::Null) => self.write(b"null"),
92            Value::Static(StaticNode::I64(number)) => self.write_int(number),
93            #[cfg(feature = "128bit")]
94            Value::Static(StaticNode::I128(number)) => self.write_int(number),
95            Value::Static(StaticNode::U64(number)) => self.write_int(number),
96            #[cfg(feature = "128bit")]
97            Value::Static(StaticNode::U128(number)) => self.write_int(number),
98            #[allow(clippy::useless_conversion)] // .into() required by ordered-float
99            Value::Static(StaticNode::F64(number)) => self.write_float(number.into()),
100            Value::Static(StaticNode::Bool(true)) => self.write(b"true"),
101            Value::Static(StaticNode::Bool(false)) => self.write(b"false"),
102            Value::String(ref string) => self.write_string(string),
103            Value::Array(ref array) => {
104                if array.is_empty() {
105                    self.write(b"[]")
106                } else {
107                    let mut iter = <[Value]>::iter(array);
108                    // We know we have one item
109
110                    let item = if let Some(v) = iter.next() {
111                        v
112                    } else {
113                        // We check against size
114                        unreachable!();
115                    };
116
117                    stry!(self.write(b"["));
118
119                    self.indent();
120                    stry!(self.new_line());
121                    stry!(self.write_json(item));
122
123                    for item in iter {
124                        stry!(self.write(b","));
125                        stry!(self.new_line());
126                        stry!(self.write_json(item));
127                    }
128
129                    self.dedent();
130                    stry!(self.new_line());
131                    self.write(b"]")
132                }
133            }
134            Value::Object(ref object) => self.write_object(object),
135        }
136    }
137}
138
139trait FastGenerator: BaseGenerator {
140    type T: Write;
141
142    #[cfg_attr(not(feature = "no-inline"), inline)]
143    fn write_object(&mut self, object: &Object) -> io::Result<()> {
144        if object.is_empty() {
145            self.write(b"{}")
146        } else {
147            let mut iter = object.iter();
148            stry!(self.write(b"{\""));
149
150            // We know this exists since it's not empty
151            let (key, value) = if let Some(v) = iter.next() {
152                v
153            } else {
154                // We check against size
155                unreachable!();
156            };
157            stry!(self.write_simple_str_content(key));
158            stry!(self.write(b"\":"));
159            stry!(self.write_json(value));
160
161            for (key, value) in iter {
162                stry!(self.write(b",\""));
163                stry!(self.write_simple_str_content(key));
164                stry!(self.write(b"\":"));
165                stry!(self.write_json(value));
166            }
167            self.write(b"}")
168        }
169    }
170
171    #[cfg_attr(not(feature = "no-inline"), inline)]
172    fn write_json(&mut self, json: &Value) -> io::Result<()> {
173        match *json {
174            Value::Static(StaticNode::Null) => self.write(b"null"),
175            Value::Static(StaticNode::I64(number)) => self.write_int(number),
176            #[cfg(feature = "128bit")]
177            Value::Static(StaticNode::I128(number)) => self.write_int(number),
178            Value::Static(StaticNode::U64(number)) => self.write_int(number),
179            #[cfg(feature = "128bit")]
180            Value::Static(StaticNode::U128(number)) => self.write_int(number),
181            #[allow(clippy::useless_conversion)] // .into() required by ordered-float
182            Value::Static(StaticNode::F64(number)) => self.write_float(number.into()),
183            Value::Static(StaticNode::Bool(true)) => self.write(b"true"),
184            Value::Static(StaticNode::Bool(false)) => self.write(b"false"),
185            Value::String(ref string) => self.write_string(string),
186            Value::Array(ref array) => {
187                if array.is_empty() {
188                    self.write(b"[]")
189                } else {
190                    let mut iter = <[Value]>::iter(array);
191                    // We know we have one item
192                    let item = if let Some(v) = iter.next() {
193                        v
194                    } else {
195                        // We check against size
196                        unreachable!();
197                    };
198
199                    stry!(self.write(b"["));
200                    stry!(self.write_json(item));
201
202                    for item in iter {
203                        stry!(self.write(b","));
204                        stry!(self.write_json(item));
205                    }
206                    self.write(b"]")
207                }
208            }
209            Value::Object(ref object) => self.write_object(object),
210        }
211    }
212}
213
214impl FastGenerator for DumpGenerator {
215    type T = Vec<u8>;
216}
217
218impl Generator for PrettyGenerator {
219    type T = Vec<u8>;
220}
221
222impl<'writer, W> FastGenerator for WriterGenerator<'writer, W>
223where
224    W: Write,
225{
226    type T = W;
227}
228
229impl<'writer, W> Generator for PrettyWriterGenerator<'writer, W>
230where
231    W: Write,
232{
233    type T = W;
234}
235
236#[cfg(test)]
237mod test {
238    use super::Value;
239    use crate::prelude::*;
240
241    #[test]
242    fn null() {
243        assert_eq!(Value::Static(StaticNode::Null).encode(), "null");
244    }
245    #[test]
246    fn bool_true() {
247        assert_eq!(Value::Static(StaticNode::Bool(true)).encode(), "true");
248    }
249    #[test]
250    fn bool_false() {
251        assert_eq!(Value::Static(StaticNode::Bool(false)).encode(), "false");
252    }
253
254    #[test]
255    fn obj() {
256        let mut o = Value::object();
257        o.insert("k", ()).expect("insert");
258        assert_eq!(o.encode(), r#"{"k":null}"#);
259    }
260    fn assert_str(from: &str, to: &str) {
261        assert_eq!(Value::String(from.into()).encode(), to);
262    }
263
264    #[test]
265    fn string() {
266        assert_str("this is a test", r#""this is a test""#);
267        assert_str(r#"this is a test ""#, r#""this is a test \"""#);
268        assert_str(r#"this is a test """#, r#""this is a test \"\"""#);
269        assert_str(
270            "this is a test a long test that should span the 32 byte boundary",
271            r#""this is a test a long test that should span the 32 byte boundary""#,
272        );
273        assert_str(
274            r#"this is a test a "long" test that should span the 32 byte boundary"#,
275            r#""this is a test a \"long\" test that should span the 32 byte boundary""#,
276        );
277
278        assert_str(
279            r#"this is a test a \"long\" test that should span the 32 byte boundary"#,
280            r#""this is a test a \\\"long\\\" test that should span the 32 byte boundary""#,
281        );
282    }
283}