facet_json/
to_json.rs

1#![allow(unreachable_code)]
2
3use facet_poke::Peek;
4use facet_trait::ShapeExt as _;
5use std::io::{self, Write};
6
7/// Serializes any Facet type to JSON
8pub fn to_json<W: Write>(peek: Peek<'_>, writer: &mut W, indent: bool) -> io::Result<()> {
9    fn serialize_value<W: Write>(
10        peek: Peek<'_>,
11        writer: &mut W,
12        indent: bool,
13        level: usize,
14    ) -> io::Result<()> {
15        match peek {
16            Peek::Value(pv) => {
17                if pv.shape().is_type::<()>() {
18                    write!(writer, "null")
19                } else if pv.shape().is_type::<bool>() {
20                    let value = unsafe { pv.data().as_ref::<bool>() };
21                    write!(writer, "{}", value)
22                } else if pv.shape().is_type::<u64>() {
23                    let value = unsafe { pv.data().as_ref::<u64>() };
24                    write!(writer, "{}", value)
25                } else if pv.shape().is_type::<String>() {
26                    let value = unsafe { pv.data().as_ref::<String>() };
27                    write!(writer, "\"{}\"", value.escape_debug())
28                } else {
29                    // For other types, we'll use a placeholder
30                    write!(writer, "\"<unsupported type>\"")
31                }
32            }
33            Peek::Struct(ps) => {
34                write!(writer, "{{")?;
35                if indent {
36                    writeln!(writer)?;
37                }
38
39                let mut first = true;
40                for field in ps.fields() {
41                    if !first {
42                        write!(writer, ",")?;
43                        if indent {
44                            writeln!(writer)?;
45                        }
46                    }
47                    first = false;
48
49                    if indent {
50                        write!(writer, "{:indent$}", "", indent = (level + 1) * 2)?;
51                    }
52                    write!(writer, "\"{}\":", field.0)?;
53                    if indent {
54                        write!(writer, " ")?;
55                    }
56
57                    serialize_value(Peek::Value(field.1), writer, indent, level + 1)?;
58                }
59
60                if !first && indent {
61                    writeln!(writer)?;
62                    write!(writer, "{:indent$}", "", indent = level * 2)?;
63                }
64                write!(writer, "}}")
65            }
66            Peek::List(_pl) => {
67                todo!("list");
68
69                write!(writer, "[")?;
70                if indent {
71                    writeln!(writer)?;
72                }
73
74                let mut first = true;
75                let mut _index = 0;
76                // while let Some(item) = pl.item_at(index) {
77                //     if !first {
78                //         write!(writer, ",")?;
79                //         if indent {
80                //             writeln!(writer)?;
81                //         }
82                //     }
83                //     first = false;
84
85                //     if indent {
86                //         write!(writer, "{:indent$}", "", indent = (level + 1) * 2)?;
87                //     }
88
89                //     serialize_value(item, writer, indent, level + 1)?;
90                //     index += 1;
91                // }
92
93                if !first && indent {
94                    writeln!(writer)?;
95                    write!(writer, "{:indent$}", "", indent = level * 2)?;
96                }
97                write!(writer, "]")
98            }
99            Peek::Map(_pm) => {
100                todo!("map");
101
102                write!(writer, "{{")?;
103                if indent {
104                    writeln!(writer)?;
105                }
106
107                let mut first = true;
108                let mut _index = 0;
109                // while let Some((key, value)) = pm.entry_at(index) {
110                //     if !first {
111                //         write!(writer, ",")?;
112                //         if indent {
113                //             writeln!(writer)?;
114                //         }
115                //     }
116                //     first = false;
117
118                //     if indent {
119                //         write!(writer, "{:indent$}", "", indent = (level + 1) * 2)?;
120                //     }
121
122                //     // Handle key serialization
123                //     serialize_value(Peek::Scalar(key), writer, false, 0)?;
124                //     write!(writer, ":")?;
125
126                //     if indent {
127                //         write!(writer, " ")?;
128                //     }
129
130                //     serialize_value(value, writer, indent, level + 1)?;
131                //     index += 1;
132                // }
133
134                if !first && indent {
135                    writeln!(writer)?;
136                    write!(writer, "{:indent$}", "", indent = level * 2)?;
137                }
138
139                write!(writer, "}}")
140            }
141        }
142    }
143
144    serialize_value(peek, writer, indent, 0)
145}
146
147/// Serializes any Facet type to JSON and returns it as a String
148pub fn to_json_string(peek: Peek<'_>, indent: bool) -> String {
149    let mut buffer = Vec::new();
150    to_json(peek, &mut buffer, indent).unwrap();
151    String::from_utf8(buffer).unwrap()
152}