1use deser::ser::SerializeDriver;
2use deser::{Atom, Error, ErrorKind, Event, Serialize};
3
4pub struct Serializer {
6 out: String,
7}
8
9enum ContainerState {
10 Map { first: bool, key_pos: bool },
11 Seq { first: bool },
12}
13
14impl Default for Serializer {
15 fn default() -> Serializer {
16 Serializer::new()
17 }
18}
19
20impl Serializer {
21 pub fn new() -> Serializer {
23 Serializer { out: String::new() }
24 }
25
26 pub fn serialize(mut self, value: &dyn Serialize) -> Result<String, Error> {
28 let mut driver = SerializeDriver::new(value);
29 let mut container_stack = Vec::new();
30
31 macro_rules! unsupported {
32 ($msg:expr) => {{
33 return Err(Error::new(ErrorKind::UnsupportedType, $msg));
34 }};
35 }
36
37 while let Some((event, _, _)) = driver.next()? {
38 match event {
40 Event::MapEnd => {
41 if !matches!(container_stack.pop(), Some(ContainerState::Map { .. })) {
42 return Err(Error::new(ErrorKind::Unexpected, "unexpected map end"));
43 }
44 self.write_char('}');
45 continue;
46 }
47 Event::SeqEnd => {
48 if !matches!(container_stack.pop(), Some(ContainerState::Seq { .. })) {
49 return Err(Error::new(ErrorKind::Unexpected, "unexpected array end"));
50 }
51 self.write_char(']');
52 continue;
53 }
54 _ => {}
55 }
56
57 if let Some(
59 ContainerState::Seq { first }
60 | ContainerState::Map {
61 first,
62 key_pos: true,
63 },
64 ) = container_stack.last_mut()
65 {
66 if !*first {
67 self.write_char(',');
68 }
69 *first = false;
70 }
71
72 if let Some(ContainerState::Map { key_pos, .. }) = container_stack.last_mut() {
74 let is_key = *key_pos;
75 *key_pos = !*key_pos;
76 if is_key {
77 match event {
78 Event::Atom(Atom::Str(val)) => self.write_escaped_str(&val),
79 Event::Atom(Atom::Char(c)) => {
80 self.write_escaped_str(&(c as u32).to_string())
81 }
82 Event::Atom(Atom::U64(val)) => {
83 self.write_char('"');
84 self.write_str(&val.to_string());
85 self.write_char('"');
86 }
87 Event::Atom(Atom::I64(val)) => {
88 self.write_char('"');
89 self.write_str(&val.to_string());
90 self.write_char('"');
91 }
92 _ => unsupported!("JSON does not support this value for map keys"),
93 }
94 self.write_char(':');
95 continue;
96 }
97 }
98
99 match event {
100 Event::Atom(atom) => match atom {
101 Atom::Null => self.write_str("null"),
102 Atom::Bool(true) => self.write_str("true"),
103 Atom::Bool(false) => self.write_str("false"),
104 Atom::Str(val) => self.write_escaped_str(&val),
105 Atom::Bytes(_val) => unsupported!("JSON doesn't support bytes"),
106 Atom::Char(c) => self.write_escaped_str(&(c as u32).to_string()),
107 Atom::U64(val) => {
108 #[cfg(feature = "speedups")]
109 {
110 self.write_str(itoa::Buffer::new().format(val))
111 }
112 #[cfg(not(feature = "speedups"))]
113 {
114 self.write_str(&val.to_string())
115 }
116 }
117 Atom::I64(val) => {
118 #[cfg(feature = "speedups")]
119 {
120 self.write_str(itoa::Buffer::new().format(val))
121 }
122 #[cfg(not(feature = "speedups"))]
123 {
124 self.write_str(&val.to_string())
125 }
126 }
127 Atom::F64(val) => {
128 if val.is_finite() {
129 #[cfg(feature = "speedups")]
130 {
131 self.write_str(ryu::Buffer::new().format_finite(val))
132 }
133 #[cfg(not(feature = "speedups"))]
134 {
135 self.write_str(val.to_string().as_str())
136 }
137 } else {
138 self.write_str("null")
139 }
140 }
141 _ => unsupported!("unknown atom"),
142 },
143 Event::MapStart => {
144 container_stack.push(ContainerState::Map {
145 first: true,
146 key_pos: true,
147 });
148 self.write_char('{')
149 }
150 Event::SeqStart => {
151 container_stack.push(ContainerState::Seq { first: true });
152 self.write_char('[')
153 }
154 Event::SeqEnd | Event::MapEnd => unreachable!(),
155 }
156 }
157
158 Ok(self.out)
159 }
160
161 fn write_str(&mut self, s: &str) {
162 self.out.push_str(s);
163 }
164
165 fn write_char(&mut self, c: char) {
166 self.out.push(c);
167 }
168
169 fn write_escaped_str(&mut self, value: &str) {
170 self.write_char('"');
171
172 let bytes = value.as_bytes();
173 let mut start = 0;
174
175 for (i, &byte) in bytes.iter().enumerate() {
176 let escape = ESCAPE[byte as usize];
177 if escape == 0 {
178 continue;
179 }
180
181 if start < i {
182 self.write_str(&value[start..i]);
183 }
184
185 match escape {
186 self::BB => self.write_str("\\b"),
187 self::TT => self.write_str("\\t"),
188 self::NN => self.write_str("\\n"),
189 self::FF => self.write_str("\\f"),
190 self::RR => self.write_str("\\r"),
191 self::QU => self.write_str("\\\""),
192 self::BS => self.write_str("\\\\"),
193 self::U => {
194 static HEX_DIGITS: [u8; 16] = *b"0123456789abcdef";
195 self.write_str("\\u00");
196 self.write_char(HEX_DIGITS[(byte >> 4) as usize] as char);
197 self.write_char(HEX_DIGITS[(byte & 0xF) as usize] as char);
198 }
199 _ => unreachable!(),
200 }
201
202 start = i + 1;
203 }
204
205 if start != bytes.len() {
206 self.write_str(&value[start..]);
207 }
208
209 self.write_char('"');
210 }
211}
212
213const BB: u8 = b'b'; const TT: u8 = b't'; const NN: u8 = b'n'; const FF: u8 = b'f'; const RR: u8 = b'r'; const QU: u8 = b'"'; const BS: u8 = b'\\'; const U: u8 = b'u'; #[rustfmt::skip]
225static ESCAPE: [u8; 256] = [
226 U, U, U, U, U, U, U, U, BB, TT, NN, U, FF, RR, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, 0, 0, QU, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, BS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ];
244
245pub fn to_string(value: &dyn Serialize) -> Result<String, Error> {
247 Serializer::new().serialize(value)
248}