1use core::num::NonZero;
2use facet_core::{Def, Facet};
3use facet_reflect::Peek;
4use std::io::{self, Write};
5
6pub fn to_string<T: Facet>(value: &T) -> String {
8 let peek = Peek::new(value);
9 let mut output = Vec::new();
10 serialize(&peek, &mut output).unwrap();
11 String::from_utf8(output).unwrap()
12}
13
14pub fn peek_to_string(peek: &Peek<'_>) -> String {
16 let mut output = Vec::new();
17 serialize(peek, &mut output).unwrap();
18 String::from_utf8(output).unwrap()
19}
20
21pub fn to_writer<T: Facet, W: Write>(value: &T, writer: &mut W) -> io::Result<()> {
23 let peek = Peek::new(value);
24 serialize(&peek, writer)
25}
26
27pub fn peek_to_writer<W: Write>(peek: &Peek<'_>, writer: &mut W) -> io::Result<()> {
29 serialize(peek, writer)
30}
31
32fn serialize<W: Write>(peek: &Peek<'_>, writer: &mut W) -> io::Result<()> {
34 match peek.shape().def {
35 Def::Scalar(_) => serialize_scalar(peek, writer),
36 Def::Struct(_) => serialize_struct(peek, writer),
37 Def::List(_) => serialize_list(peek, writer),
38 Def::Map(_) => serialize_map(peek, writer),
39 Def::Enum(_) => serialize_enum(peek, writer),
40 Def::Option(_) => serialize_option(peek, writer),
41 _ => Err(io::Error::new(
42 io::ErrorKind::Other,
43 format!("Unsupported type: {}", peek.shape()),
44 )),
45 }
46}
47
48fn serialize_scalar<W: Write>(peek: &Peek<'_>, writer: &mut W) -> io::Result<()> {
50 if peek.shape().is_type::<bool>() {
52 let value = peek.get::<bool>().unwrap();
53 write!(writer, "{}", if *value { "true" } else { "false" })
54 } else if peek.shape().is_type::<String>() {
55 let value = peek.get::<String>().unwrap();
56 write_json_string(writer, value)
57 } else if peek.shape().is_type::<&str>() {
58 let value = peek.get::<&str>().unwrap();
59 write_json_string(writer, value)
60 } else if peek.shape().is_type::<alloc::borrow::Cow<'_, str>>() {
61 let value = peek.get::<alloc::borrow::Cow<'_, str>>().unwrap();
62 write_json_string(writer, value)
63 }
64 else if peek.shape().is_type::<u8>() {
66 let value = peek.get::<u8>().unwrap();
67 write!(writer, "{}", value)
68 } else if peek.shape().is_type::<u16>() {
69 let value = peek.get::<u16>().unwrap();
70 write!(writer, "{}", value)
71 } else if peek.shape().is_type::<u32>() {
72 let value = peek.get::<u32>().unwrap();
73 write!(writer, "{}", value)
74 } else if peek.shape().is_type::<u64>() {
75 let value = peek.get::<u64>().unwrap();
76 write!(writer, "{}", value)
77 } else if peek.shape().is_type::<usize>() {
78 let value = peek.get::<usize>().unwrap();
79 write!(writer, "{}", value)
80 } else if peek.shape().is_type::<i8>() {
81 let value = peek.get::<i8>().unwrap();
82 write!(writer, "{}", value)
83 } else if peek.shape().is_type::<i16>() {
84 let value = peek.get::<i16>().unwrap();
85 write!(writer, "{}", value)
86 } else if peek.shape().is_type::<i32>() {
87 let value = peek.get::<i32>().unwrap();
88 write!(writer, "{}", value)
89 } else if peek.shape().is_type::<i64>() {
90 let value = peek.get::<i64>().unwrap();
91 write!(writer, "{}", value)
92 } else if peek.shape().is_type::<isize>() {
93 let value = peek.get::<isize>().unwrap();
94 write!(writer, "{}", value)
95 }
96 else if peek.shape().is_type::<NonZero<u8>>() {
98 let value = peek.get::<NonZero<u8>>().unwrap();
99 write!(writer, "{}", value)
100 } else if peek.shape().is_type::<NonZero<u16>>() {
101 let value = peek.get::<NonZero<u16>>().unwrap();
102 write!(writer, "{}", value)
103 } else if peek.shape().is_type::<NonZero<u32>>() {
104 let value = peek.get::<NonZero<u32>>().unwrap();
105 write!(writer, "{}", value)
106 } else if peek.shape().is_type::<NonZero<u64>>() {
107 let value = peek.get::<NonZero<u64>>().unwrap();
108 write!(writer, "{}", value)
109 } else if peek.shape().is_type::<NonZero<usize>>() {
110 let value = peek.get::<NonZero<usize>>().unwrap();
111 write!(writer, "{}", value)
112 } else if peek.shape().is_type::<NonZero<i8>>() {
113 let value = peek.get::<NonZero<i8>>().unwrap();
114 write!(writer, "{}", value)
115 } else if peek.shape().is_type::<NonZero<i16>>() {
116 let value = peek.get::<NonZero<i16>>().unwrap();
117 write!(writer, "{}", value)
118 } else if peek.shape().is_type::<NonZero<i32>>() {
119 let value = peek.get::<NonZero<i32>>().unwrap();
120 write!(writer, "{}", value)
121 } else if peek.shape().is_type::<NonZero<i64>>() {
122 let value = peek.get::<NonZero<i64>>().unwrap();
123 write!(writer, "{}", value)
124 } else if peek.shape().is_type::<NonZero<isize>>() {
125 let value = peek.get::<NonZero<isize>>().unwrap();
126 write!(writer, "{}", value)
127 }
128 else if peek.shape().is_type::<f32>() {
130 let value = peek.get::<f32>().unwrap();
131 write!(writer, "{}", value)
132 } else if peek.shape().is_type::<f64>() {
133 let value = peek.get::<f64>().unwrap();
134 write!(writer, "{}", value)
135 } else {
136 Err(io::Error::new(
137 io::ErrorKind::Other,
138 format!("Unsupported scalar type: {}", peek.shape()),
139 ))
140 }
141}
142
143fn serialize_struct<W: Write>(peek: &Peek<'_>, writer: &mut W) -> io::Result<()> {
145 let struct_peek = peek
146 .into_struct()
147 .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("Not a struct: {}", e)))?;
148
149 write!(writer, "{{")?;
150
151 let mut first = true;
152 for (field, field_peek) in struct_peek.fields() {
153 if !first {
154 write!(writer, ",")?;
155 }
156 first = false;
157
158 write_json_string(writer, field.name)?;
160 write!(writer, ":")?;
161
162 serialize(&field_peek, writer)?;
164 }
165
166 write!(writer, "}}")?;
167
168 Ok(())
169}
170
171fn serialize_list<W: Write>(peek: &Peek<'_>, writer: &mut W) -> io::Result<()> {
173 let list_peek = peek
174 .into_list()
175 .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("Not a list: {}", e)))?;
176
177 write!(writer, "[")?;
178
179 let mut first = true;
180 for item_peek in list_peek.iter() {
181 if !first {
182 write!(writer, ",")?;
183 }
184 first = false;
185
186 serialize(&item_peek, writer)?;
187 }
188
189 write!(writer, "]")?;
190
191 Ok(())
192}
193
194fn serialize_map<W: Write>(peek: &Peek<'_>, writer: &mut W) -> io::Result<()> {
196 let map_peek = peek
197 .into_map()
198 .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("Not a map: {}", e)))?;
199
200 write!(writer, "{{")?;
201
202 let mut first = true;
203 for (key, value) in map_peek.iter() {
204 if !first {
205 write!(writer, ",")?;
206 }
207 first = false;
208
209 match key.shape().def {
211 Def::Scalar(_) => {
212 if key.shape().is_type::<String>() {
214 let key_str = key.get::<String>().unwrap();
215 write_json_string(writer, key_str)?;
216 } else {
217 write!(writer, "\"{}\"", key)?;
219 }
220 }
221 _ => {
222 return Err(io::Error::new(
223 io::ErrorKind::Other,
224 format!("Map keys must be scalar types, got: {}", key.shape()),
225 ));
226 }
227 }
228
229 write!(writer, ":")?;
230
231 serialize(&value, writer)?;
233 }
234
235 write!(writer, "}}")?;
236
237 Ok(())
238}
239
240fn serialize_enum<W: Write>(peek: &Peek<'_>, writer: &mut W) -> io::Result<()> {
242 let enum_peek = peek
243 .into_enum()
244 .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("Not an enum: {}", e)))?;
245
246 let variant = enum_peek.active_variant();
247 let variant_name = variant.name;
248
249 if variant.data.fields.is_empty() {
251 write_json_string(writer, variant_name)
253 } else {
254 write!(writer, "{{")?;
256 write_json_string(writer, variant_name)?;
257 write!(writer, ":")?;
258
259 if variant.data.fields.len() == 1 {
261 let field = enum_peek.field(0).ok_or_else(|| {
262 io::Error::new(io::ErrorKind::Other, "Failed to access enum field")
263 })?;
264 serialize(&field, writer)?;
265 } else {
266 let is_struct = variant
268 .data
269 .fields
270 .iter()
271 .any(|f| !f.name.starts_with("__"));
272
273 if is_struct {
274 write!(writer, "{{")?;
276
277 let mut first = true;
278 for i in 0..variant.data.fields.len() {
279 let field = enum_peek.field(i).ok_or_else(|| {
280 io::Error::new(
281 io::ErrorKind::Other,
282 format!("Failed to access enum field {}", i),
283 )
284 })?;
285 let field_name = variant.data.fields[i].name;
286
287 if !first {
288 write!(writer, ",")?;
289 }
290 first = false;
291
292 write_json_string(writer, field_name)?;
293 write!(writer, ":")?;
294 serialize(&field, writer)?;
295 }
296
297 write!(writer, "}}")?
298 } else {
299 write!(writer, "[")?;
301
302 let mut first = true;
303 for i in 0..variant.data.fields.len() {
304 if !first {
305 write!(writer, ",")?;
306 }
307 first = false;
308
309 let field = enum_peek.field(i).ok_or_else(|| {
310 io::Error::new(
311 io::ErrorKind::Other,
312 format!("Failed to access enum field {}", i),
313 )
314 })?;
315 serialize(&field, writer)?;
316 }
317
318 write!(writer, "]")?;
319 }
320 }
321
322 write!(writer, "}}")?;
323 Ok(())
324 }
325}
326
327fn serialize_option<W: Write>(peek: &Peek<'_>, writer: &mut W) -> io::Result<()> {
329 let option_peek = peek
330 .into_option()
331 .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("Not an option: {}", e)))?;
332
333 if option_peek.is_none() {
334 write!(writer, "null")
335 } else {
336 let value = option_peek
337 .value()
338 .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Failed to get option value"))?;
339 serialize(&value, writer)
340 }
341}
342
343fn write_json_string<W: Write>(writer: &mut W, s: &str) -> io::Result<()> {
345 write!(writer, "\"")?;
346
347 for c in s.chars() {
348 match c {
349 '"' => write!(writer, "\\\"")?,
350 '\\' => write!(writer, "\\\\")?,
351 '\n' => write!(writer, "\\n")?,
352 '\r' => write!(writer, "\\r")?,
353 '\t' => write!(writer, "\\t")?,
354 '\u{08}' => write!(writer, "\\b")?,
355 '\u{0C}' => write!(writer, "\\f")?,
356 c if c.is_control() => write!(writer, "\\u{:04x}", c as u32)?,
357 c => write!(writer, "{}", c)?,
358 }
359 }
360
361 write!(writer, "\"")
362}