facet_csv_legacy/
serialize.rs

1use facet_core::{Def, Facet, StructKind, Type, UserType};
2use facet_reflect::{HasFields, Peek, ScalarType};
3use std::io::{self, Write};
4
5/// Serializes a value to CSV
6pub fn to_string<'facet, T: Facet<'facet>>(value: &'facet T) -> String {
7    let peek = Peek::new(value);
8    let mut output = Vec::new();
9    let mut serializer = CsvSerializer::new(&mut output);
10    serialize_value(peek, &mut serializer).unwrap();
11    String::from_utf8(output).unwrap()
12}
13
14/// Serializes a Peek instance to CSV
15pub fn peek_to_string<'facet>(peek: Peek<'_, 'facet>) -> String {
16    let mut output = Vec::new();
17    let mut serializer = CsvSerializer::new(&mut output);
18    serialize_value(peek, &mut serializer).unwrap();
19    String::from_utf8(output).unwrap()
20}
21
22/// Serializes a value to a writer in CSV format
23pub fn to_writer<'a, T: Facet<'a>, W: Write>(value: &'a T, writer: &mut W) -> io::Result<()> {
24    let peek = Peek::new(value);
25    let mut serializer = CsvSerializer::new(writer);
26    serialize_value(peek, &mut serializer)
27}
28
29/// Serializes a Peek instance to a writer in CSV format
30pub fn peek_to_writer<'facet, W: Write>(peek: Peek<'_, 'facet>, writer: &mut W) -> io::Result<()> {
31    let mut serializer = CsvSerializer::new(writer);
32    serialize_value(peek, &mut serializer)
33}
34
35/// A struct to handle the CSV serializer logic
36pub struct CsvSerializer<W> {
37    /// Owned writer
38    writer: W,
39
40    /// The current position in a row
41    pos: usize,
42
43    /// Initialized by `start_object`
44    n_fields: usize,
45
46    /// Delimeter used to separate values
47    delim: &'static [u8],
48
49    /// Newline encoding
50    newline: &'static [u8],
51}
52
53impl<W> CsvSerializer<W>
54where
55    W: Write,
56{
57    /// Initializes a new CSV Serializer
58    pub fn new(writer: W) -> Self {
59        Self {
60            writer,
61            pos: 0,
62            n_fields: 0,
63            delim: b",",
64            newline: b"\n",
65        }
66    }
67
68    fn set_n_fields(&mut self, n_fields: usize) {
69        self.n_fields = n_fields;
70    }
71
72    /// Conditionally prefix the value with the required delimeter
73    fn start_value(&mut self) -> Result<(), io::Error> {
74        if self.pos == 0 {
75            // no prefix
76            Ok(())
77        } else {
78            self.writer.write_all(self.delim)
79        }
80    }
81
82    /// Conditionally suffix the value with the required newline
83    fn end_value(&mut self) -> Result<(), io::Error> {
84        if self.pos == self.n_fields - 1 {
85            // Reset the position to zero
86            self.pos = 0;
87            self.writer.write_all(self.newline)
88        } else {
89            // Increment the position
90            self.pos += 1;
91            // no suffix
92            Ok(())
93        }
94    }
95
96    fn write_empty(&mut self) -> io::Result<()> {
97        self.start_value()?;
98        self.end_value()
99    }
100}
101
102fn serialize_value<W: Write>(peek: Peek<'_, '_>, ser: &mut CsvSerializer<W>) -> io::Result<()> {
103    match (peek.shape().def, peek.shape().ty) {
104        (Def::Scalar, _) => {
105            let peek = peek.innermost_peek();
106            serialize_scalar(peek, ser)
107        }
108        (Def::Option(_), _) => {
109            let opt = peek.into_option().unwrap();
110            if let Some(inner) = opt.value() {
111                serialize_value(inner, ser)
112            } else {
113                ser.write_empty()
114            }
115        }
116        (Def::Pointer(_), _) => {
117            let ptr = peek.into_pointer().unwrap();
118            if let Some(inner) = ptr.borrow_inner() {
119                serialize_value(inner, ser)
120            } else {
121                ser.write_empty()
122            }
123        }
124        (_, Type::User(UserType::Struct(sd))) => {
125            match sd.kind {
126                StructKind::Unit => {
127                    // Unit structs serialize as empty
128                    ser.write_empty()
129                }
130                StructKind::Tuple | StructKind::TupleStruct | StructKind::Struct => {
131                    let ps = peek.into_struct().unwrap();
132                    let fields: Vec<_> = ps.fields_for_serialize().collect();
133                    ser.set_n_fields(fields.len());
134                    for (_, field_value) in fields {
135                        serialize_value(field_value, ser)?;
136                    }
137                    Ok(())
138                }
139            }
140        }
141        (_, Type::User(UserType::Enum(_))) => {
142            // Unit variants should not serialize to anything
143            ser.write_empty()
144        }
145        (_, Type::Pointer(_)) => {
146            // Handle string types
147            if let Some(s) = peek.as_str() {
148                ser.start_value()?;
149                write!(ser.writer, "{s}")?;
150                ser.end_value()
151            } else {
152                let innermost = peek.innermost_peek();
153                if innermost.shape() != peek.shape() {
154                    serialize_value(innermost, ser)
155                } else {
156                    ser.write_empty()
157                }
158            }
159        }
160        _ => {
161            // Unsupported types serialize as empty
162            ser.write_empty()
163        }
164    }
165}
166
167fn serialize_scalar<W: Write>(peek: Peek<'_, '_>, ser: &mut CsvSerializer<W>) -> io::Result<()> {
168    match peek.scalar_type() {
169        Some(ScalarType::Unit) => ser.write_empty(),
170        Some(ScalarType::Bool) => {
171            let v = *peek.get::<bool>().unwrap();
172            ser.start_value()?;
173            write!(ser.writer, "{}", if v { "true" } else { "false" })?;
174            ser.end_value()
175        }
176        Some(ScalarType::Char) => {
177            let c = *peek.get::<char>().unwrap();
178            ser.start_value()?;
179            write!(ser.writer, "{c}")?;
180            ser.end_value()
181        }
182        Some(ScalarType::Str) => {
183            let s = peek.get::<str>().unwrap();
184            ser.start_value()?;
185            write!(ser.writer, "{s}")?;
186            ser.end_value()
187        }
188        Some(ScalarType::String) => {
189            let s = peek.get::<String>().unwrap();
190            ser.start_value()?;
191            write!(ser.writer, "{s}")?;
192            ser.end_value()
193        }
194        Some(ScalarType::CowStr) => {
195            let s = peek.get::<alloc::borrow::Cow<'_, str>>().unwrap();
196            ser.start_value()?;
197            write!(ser.writer, "{s}")?;
198            ser.end_value()
199        }
200        Some(ScalarType::F32) => {
201            let v = *peek.get::<f32>().unwrap();
202            ser.start_value()?;
203            write!(ser.writer, "{v}")?;
204            ser.end_value()
205        }
206        Some(ScalarType::F64) => {
207            let v = *peek.get::<f64>().unwrap();
208            ser.start_value()?;
209            write!(ser.writer, "{v}")?;
210            ser.end_value()
211        }
212        Some(ScalarType::U8) => {
213            let v = *peek.get::<u8>().unwrap();
214            ser.start_value()?;
215            write!(ser.writer, "{v}")?;
216            ser.end_value()
217        }
218        Some(ScalarType::U16) => {
219            let v = *peek.get::<u16>().unwrap();
220            ser.start_value()?;
221            write!(ser.writer, "{v}")?;
222            ser.end_value()
223        }
224        Some(ScalarType::U32) => {
225            let v = *peek.get::<u32>().unwrap();
226            ser.start_value()?;
227            write!(ser.writer, "{v}")?;
228            ser.end_value()
229        }
230        Some(ScalarType::U64) => {
231            let v = *peek.get::<u64>().unwrap();
232            ser.start_value()?;
233            write!(ser.writer, "{v}")?;
234            ser.end_value()
235        }
236        Some(ScalarType::U128) => {
237            let v = *peek.get::<u128>().unwrap();
238            ser.start_value()?;
239            write!(ser.writer, "{v}")?;
240            ser.end_value()
241        }
242        Some(ScalarType::USize) => {
243            let v = *peek.get::<usize>().unwrap();
244            ser.start_value()?;
245            write!(ser.writer, "{v}")?;
246            ser.end_value()
247        }
248        Some(ScalarType::I8) => {
249            let v = *peek.get::<i8>().unwrap();
250            ser.start_value()?;
251            write!(ser.writer, "{v}")?;
252            ser.end_value()
253        }
254        Some(ScalarType::I16) => {
255            let v = *peek.get::<i16>().unwrap();
256            ser.start_value()?;
257            write!(ser.writer, "{v}")?;
258            ser.end_value()
259        }
260        Some(ScalarType::I32) => {
261            let v = *peek.get::<i32>().unwrap();
262            ser.start_value()?;
263            write!(ser.writer, "{v}")?;
264            ser.end_value()
265        }
266        Some(ScalarType::I64) => {
267            let v = *peek.get::<i64>().unwrap();
268            ser.start_value()?;
269            write!(ser.writer, "{v}")?;
270            ser.end_value()
271        }
272        Some(ScalarType::I128) => {
273            let v = *peek.get::<i128>().unwrap();
274            ser.start_value()?;
275            write!(ser.writer, "{v}")?;
276            ser.end_value()
277        }
278        Some(ScalarType::ISize) => {
279            let v = *peek.get::<isize>().unwrap();
280            ser.start_value()?;
281            write!(ser.writer, "{v}")?;
282            ser.end_value()
283        }
284        Some(_) | None => {
285            // Unknown scalar - try to display it
286            ser.start_value()?;
287            write!(ser.writer, "{peek}")?;
288            ser.end_value()
289        }
290    }
291}