simd_json/value/borrowed/
serialize.rs

1// This is mostly taken from json-rust's codegen
2// as it seems to perform well and it makes snense 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<'value> Writable for Value<'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                    stry!(self.write(b"["));
117                    self.indent();
118
119                    stry!(self.new_line());
120                    stry!(self.write_json(item));
121
122                    for item in iter {
123                        stry!(self.write(b","));
124                        stry!(self.new_line());
125                        stry!(self.write_json(item));
126                    }
127                    self.dedent();
128                    stry!(self.new_line());
129                    self.write(b"]")
130                }
131            }
132            Value::Object(ref object) => self.write_object(object),
133        }
134    }
135}
136
137trait FastGenerator: BaseGenerator {
138    type T: Write;
139
140    #[cfg_attr(not(feature = "no-inline"), inline)]
141    fn write_object(&mut self, object: &Object) -> io::Result<()> {
142        if object.is_empty() {
143            self.write(b"{}")
144        } else {
145            let mut iter = object.iter();
146            stry!(self.write(b"{\""));
147
148            // We know this exists since it's not empty
149            let (key, value) = if let Some(v) = iter.next() {
150                v
151            } else {
152                // We check against size
153                unreachable!();
154            };
155            stry!(self.write_simple_str_content(key));
156            stry!(self.write(b"\":"));
157            stry!(self.write_json(value));
158
159            for (key, value) in iter {
160                stry!(self.write(b",\""));
161                stry!(self.write_simple_str_content(key));
162                stry!(self.write(b"\":"));
163                stry!(self.write_json(value));
164            }
165            self.write(b"}")
166        }
167    }
168
169    #[cfg_attr(not(feature = "no-inline"), inline)]
170    fn write_json(&mut self, json: &Value) -> io::Result<()> {
171        match *json {
172            Value::Static(StaticNode::Null) => self.write(b"null"),
173            Value::Static(StaticNode::I64(number)) => self.write_int(number),
174            #[cfg(feature = "128bit")]
175            Value::Static(StaticNode::I128(number)) => self.write_int(number),
176            Value::Static(StaticNode::U64(number)) => self.write_int(number),
177            #[cfg(feature = "128bit")]
178            Value::Static(StaticNode::U128(number)) => self.write_int(number),
179            #[allow(clippy::useless_conversion)] // .into() required by ordered-float
180            Value::Static(StaticNode::F64(number)) => self.write_float(number.into()),
181            Value::Static(StaticNode::Bool(true)) => self.write(b"true"),
182            Value::Static(StaticNode::Bool(false)) => self.write(b"false"),
183            Value::String(ref string) => self.write_string(string),
184            Value::Array(ref array) => {
185                if array.is_empty() {
186                    self.write(b"[]")
187                } else {
188                    let mut iter = <[Value]>::iter(array);
189                    // We know we have one item
190                    let item = if let Some(v) = iter.next() {
191                        v
192                    } else {
193                        // We check against size
194                        unreachable!();
195                    };
196
197                    stry!(self.write(b"["));
198                    stry!(self.write_json(item));
199
200                    for item in iter {
201                        stry!(self.write(b","));
202                        stry!(self.write_json(item));
203                    }
204                    self.write(b"]")
205                }
206            }
207            Value::Object(ref object) => self.write_object(object),
208        }
209    }
210}
211
212impl FastGenerator for DumpGenerator {
213    type T = Vec<u8>;
214}
215
216impl Generator for PrettyGenerator {
217    type T = Vec<u8>;
218}
219
220impl<'writer, W> FastGenerator for WriterGenerator<'writer, W>
221where
222    W: Write,
223{
224    type T = W;
225}
226
227impl<'writer, W> Generator for PrettyWriterGenerator<'writer, W>
228where
229    W: Write,
230{
231    type T = W;
232}
233
234#[cfg(test)]
235mod test {
236    use super::Value;
237    use crate::prelude::*;
238
239    #[test]
240    fn null() {
241        assert_eq!(Value::Static(StaticNode::Null).encode(), "null");
242    }
243    #[test]
244    fn bool_true() {
245        assert_eq!(Value::Static(StaticNode::Bool(true)).encode(), "true");
246    }
247    #[test]
248    fn bool_false() {
249        assert_eq!(Value::Static(StaticNode::Bool(false)).encode(), "false");
250    }
251
252    #[test]
253    fn obj() {
254        let mut o = Value::object();
255        o.insert("k", ()).expect("insert");
256        assert_eq!(o.encode(), r#"{"k":null}"#);
257    }
258
259    fn assert_str(from: &str, to: &str) {
260        assert_eq!(Value::String(from.into()).encode(), to);
261    }
262    #[test]
263    fn string() {
264        assert_str("this is a test", r#""this is a test""#);
265        assert_str(r#"this is a test ""#, r#""this is a test \"""#);
266        assert_str(r#"this is a test """#, r#""this is a test \"\"""#);
267        assert_str(
268            "this is a test a long test that should span the 32 byte boundary",
269            r#""this is a test a long test that should span the 32 byte boundary""#,
270        );
271        assert_str(
272            r#"this is a test a "long" test that should span the 32 byte boundary"#,
273            r#""this is a test a \"long\" test that should span the 32 byte boundary""#,
274        );
275
276        assert_str(
277            r#"this is a test a \"long\" test that should span the 32 byte boundary"#,
278            r#""this is a test a \\\"long\\\" test that should span the 32 byte boundary""#,
279        );
280    }
281}