1use std::io::Write;
10
11use super::Value;
12use crate::Result;
13
14const QU: u8 = b'"';
15const BS: u8 = b'\\';
16const BB: u8 = b'b';
17const TT: u8 = b't';
18const NN: u8 = b'n';
19const FF: u8 = b'f';
20const RR: u8 = b'r';
21const UU: u8 = b'u';
22const __: u8 = 0;
23
24static ESCAPED: [u8; 256] = [
26 UU, UU, UU, UU, UU, UU, UU, UU, BB, TT, NN, UU, FF, RR, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, __, __, QU, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, BS, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, ];
44
45pub trait Formatter {
46 fn write_min(&self, output: &mut Vec<u8>, slice: &[u8], min: u8);
47 fn new_line(&self, output: &mut Vec<u8>);
48 fn indent(&mut self);
49 fn dedent(&mut self);
50}
51
52pub struct DumpFormatter;
53
54impl Formatter for DumpFormatter {
55 #[inline(always)]
56 fn write_min(&self, output: &mut Vec<u8>, _: &[u8], min: u8) {
57 output.push(min);
58 }
59
60 #[inline(always)]
61 fn new_line(&self, _output: &mut Vec<u8>) {}
62
63 #[inline(always)]
64 fn indent(&mut self) {}
65
66 #[inline(always)]
67 fn dedent(&mut self) {}
68}
69
70pub struct PrettyFormatter {
71 dent: u16,
72 spaces: u16,
73}
74
75impl Default for PrettyFormatter {
76 fn default() -> Self {
77 Self { dent: 0, spaces: 2 }
78 }
79}
80
81impl Formatter for PrettyFormatter {
82 #[inline(always)]
83 fn write_min(&self, output: &mut Vec<u8>, slice: &[u8], _: u8) {
84 output.extend_from_slice(slice);
85 }
86
87 fn new_line(&self, output: &mut Vec<u8>) {
88 output.push(b'\n');
89 for _ in 0..(self.dent * self.spaces) {
90 output.push(b' ');
91 }
92 }
93
94 fn indent(&mut self) {
95 self.dent += 1;
96 }
97
98 fn dedent(&mut self) {
99 self.dent -= 1;
100 }
101}
102
103pub struct Serializer<T: Formatter> {
104 output: Vec<u8>,
105 formatter: T,
106 fail_on_invalid_numbers: bool,
107}
108
109impl<T: Formatter> Serializer<T> {
110 pub fn new(formatter: T, fail_on_invalid_numbers: bool) -> Self {
111 Serializer {
112 output: Vec::with_capacity(1024),
113 formatter,
114 fail_on_invalid_numbers,
115 }
116 }
117
118 pub fn serialize<'a>(mut self, value: &'a Value<'a>) -> Result<String> {
119 self.write_json(value)?;
120
121 Ok(unsafe { String::from_utf8_unchecked(self.output) })
124 }
125
126 #[inline(always)]
127 fn write(&mut self, slice: &[u8]) {
128 self.output.extend_from_slice(slice);
129 }
130
131 #[inline(always)]
132 fn write_char(&mut self, ch: u8) {
133 self.output.push(ch);
134 }
135
136 #[inline(never)]
137 fn write_string_complex(&mut self, string: &str, mut start: usize) {
138 self.write(&string.as_bytes()[..start]);
139
140 for (index, ch) in string.bytes().enumerate().skip(start) {
141 let escape = ESCAPED[ch as usize];
142 if escape > 0 {
143 self.write(&string.as_bytes()[start..index]);
144 self.write(&[b'\\', escape]);
145 start = index + 1;
146 }
147 if escape == b'u' {
148 write!(self.output, "{:04x}", ch).unwrap();
149 }
150 }
151 self.write(&string.as_bytes()[start..]);
152
153 self.write_char(b'"');
154 }
155
156 #[inline(always)]
157 fn write_string(&mut self, string: &str) {
158 self.write_char(b'"');
159
160 for (index, ch) in string.bytes().enumerate() {
161 if ESCAPED[ch as usize] > 0 {
162 self.write_string_complex(string, index);
163 return;
164 }
165 }
166
167 self.write(string.as_bytes());
168 self.write_char(b'"');
169 }
170
171 #[inline(always)]
172 fn write_number(&mut self, number: f64) {
173 const MAX_SIGNIFICANT_DIGITS: usize = 15;
174
175 if number.is_finite() {
176 let mut buffer = dtoa::Buffer::new();
177 let formatted = buffer.format_finite(number).as_bytes();
178
179 let mut split_iter = formatted.split(|b| *b == b'.');
190 let whole = split_iter.next();
191 let fraction = split_iter.next();
192 if let Some(whole) = whole {
193 self.write(whole);
194 if whole.len() < MAX_SIGNIFICANT_DIGITS {
195 if let Some(fraction) = fraction {
196 let fraction_length =
197 usize::min(MAX_SIGNIFICANT_DIGITS - whole.len(), fraction.len());
198 if fraction_length > 0 {
199 let fraction = unsafe {
200 std::str::from_utf8_unchecked(&fraction[0..fraction_length])
201 .trim_end_matches('0')
202 };
203 if !fraction.is_empty() {
204 self.write_char(b'.');
205 self.write(fraction.as_bytes());
206 }
207 }
208 }
209 }
210 } else {
211 self.write(formatted);
212 }
213 } else {
214 self.write(b"null");
215 }
216 }
217
218 #[inline(always)]
219 fn write_object<'a>(&mut self, object: &'a Value<'a>) -> Result<()> {
220 self.write_char(b'{');
221 let mut iter = object.entries();
222
223 if let Some((key, value)) = iter.next() {
224 self.formatter.indent();
225 self.formatter.new_line(&mut self.output);
226 self.write_string(key);
227 self.formatter.write_min(&mut self.output, b": ", b':');
228 self.write_json(value)?;
229 } else {
230 self.write_char(b'}');
231 return Ok(());
232 }
233
234 for (key, value) in iter {
235 self.write_char(b',');
236 self.formatter.new_line(&mut self.output);
237 self.write_string(key);
238 self.formatter.write_min(&mut self.output, b": ", b':');
239 self.write_json(value)?;
240 }
241
242 self.formatter.dedent();
243 self.formatter.new_line(&mut self.output);
244 self.write_char(b'}');
245
246 Ok(())
247 }
248
249 #[inline(always)]
250 fn write_array<'a>(&mut self, array: &'a Value<'a>) -> Result<()> {
251 self.write_char(b'[');
252 let mut iter = array.members();
253
254 if let Some(item) = iter.next() {
255 self.formatter.indent();
256 self.formatter.new_line(&mut self.output);
257 self.write_json(item)?;
258 } else {
259 self.write_char(b']');
260 return Ok(());
261 }
262
263 for item in iter {
264 self.write_char(b',');
265 self.formatter.new_line(&mut self.output);
266 self.write_json(item)?;
267 }
268
269 self.formatter.dedent();
270 self.formatter.new_line(&mut self.output);
271 self.write_char(b']');
272
273 Ok(())
274 }
275
276 fn write_json<'a>(&mut self, value: &'a Value<'a>) -> Result<()> {
277 match value {
278 Value::Undefined => {}
279 Value::Null => self.write(b"null"),
280 Value::String(ref string) => self.write_string(string),
281 Value::Number(n) => {
282 if self.fail_on_invalid_numbers {
283 value.is_valid_number()?;
284 }
285 self.write_number(*n);
286 }
287 Value::Bool(true) => self.write(b"true"),
288 Value::Bool(false) => self.write(b"false"),
289 Value::Array(..) | Value::Range(..) => self.write_array(value)?,
290 Value::Object(..) => self.write_object(value)?,
291 Value::Lambda { .. } | Value::NativeFn { .. } => self.write(b"\"\""),
292 };
293
294 Ok(())
295 }
296}