serde_csv_core/
ser.rs

1//! Serialize a Rust data structure into CSV data.
2
3use core::borrow::Borrow;
4#[cfg(feature = "heapless")]
5use heapless::Vec;
6use serde::{ser, Serialize};
7
8/// Wrapper for [`csv_core::Writer`] that provides methods for serialization using [`serde`].
9#[derive(Debug)]
10pub struct Writer {
11    inner: csv_core::Writer,
12}
13
14impl Default for Writer {
15    fn default() -> Self {
16        Self::from_builder(csv_core::WriterBuilder::new())
17    }
18}
19
20impl Writer {
21    /// Constructs a new writer.
22    pub fn new() -> Self {
23        Self::default()
24    }
25
26    /// Constructs a new writer from [`csv_core::WriterBuilder`].
27    ///
28    /// # Example
29    /// ```
30    /// use serde_csv_core::csv_core;
31    ///
32    /// let writer = serde_csv_core::Writer::from_builder(
33    ///     csv_core::WriterBuilder::new()
34    ///         .delimiter(b'-')
35    /// );
36    /// ```
37    pub fn from_builder(builder: impl Borrow<csv_core::WriterBuilder>) -> Self {
38        Self {
39            inner: builder.borrow().build(),
40        }
41    }
42
43    /// Serializes the given value as a CSV byte slice.
44    ///
45    /// Inserts record terminator after the serialized value.
46    /// Flattens compound types (e.g. nested structs, tuples, vectors).
47    /// On success, it returns the number of bytes written.
48    ///
49    /// # Example
50    /// ```
51    /// use heapless::String;
52    ///
53    /// #[derive(serde::Serialize)]
54    /// struct Record {
55    ///     pub country: String<32>,
56    ///     pub city: String<32>,
57    ///     pub population: u32,
58    /// }
59    ///
60    /// let record = Record {
61    ///     country: "Poland".into(),
62    ///     city: "Cracow".into(),
63    ///     population: 766_683,
64    /// };
65    ///
66    /// let mut writer = serde_csv_core::Writer::new();
67    /// let mut csv = [0; 32];
68    /// let nwritten = writer.serialize(&record, &mut csv)?;
69    ///
70    /// assert_eq!(&csv[..nwritten], b"Poland,Cracow,766683\n");
71    /// # Ok::<(), serde_csv_core::ser::Error>(())
72    /// ```
73    pub fn serialize<T>(&mut self, value: &T, output: &mut [u8]) -> Result<usize>
74    where
75        T: Serialize + ?Sized,
76    {
77        let mut nwritten = 0;
78
79        let mut serializer = Serializer::new(&mut self.inner, output);
80        value.serialize(&mut serializer)?;
81        nwritten += serializer.bytes_written();
82
83        let (result, n) = self.inner.terminator(&mut output[nwritten..]);
84        if result == csv_core::WriteResult::OutputFull {
85            return Err(Error::Overflow);
86        }
87        nwritten += n;
88
89        Ok(nwritten)
90    }
91
92    /// Serializes the given value as a CSV byte vector.
93    ///
94    /// Inserts record terminator after the serialized value.
95    /// Flattens compound types (e.g. nested structs, tuples, vectors).
96    ///
97    /// # Example
98    /// ```
99    /// use heapless::{String, Vec};
100    ///
101    /// #[derive(serde::Serialize)]
102    /// struct Record {
103    ///     pub country: String<32>,
104    ///     pub city: String<32>,
105    ///     pub population: u32
106    /// }
107    ///
108    /// let record = Record {
109    ///     country: "Poland".into(),
110    ///     city: "Cracow".into(),
111    ///     population: 766_683
112    /// };
113    ///
114    /// let mut writer = serde_csv_core::Writer::new();
115    /// let buf: Vec<u8, 32> = writer.serialize_to_vec(&record)?;
116    ///
117    /// assert_eq!(&buf, b"Poland,Cracow,766683\n");
118    /// # Ok::<(), serde_csv_core::ser::Error>(())
119    /// ```
120    /// Serializes the given value as a CSV byte vector.
121    ///
122    /// Inserts record terminator after the serialized value.
123    /// Flattens compound types (e.g. nested structs, tuples, vectors).
124    #[cfg(feature = "heapless")]
125    pub fn serialize_to_vec<T, const N: usize>(&mut self, value: &T) -> Result<Vec<u8, N>>
126    where
127        T: Serialize + ?Sized,
128    {
129        let mut buf: Vec<u8, N> = Vec::new();
130        // SAFETY:
131        // always safe since buf has capacity N
132        unsafe { buf.resize_default(N).unwrap_unchecked() };
133
134        let len = self.serialize(value, &mut buf)?;
135        buf.truncate(len);
136        Ok(buf)
137    }
138}
139
140/// This type represents all possible errors that can occur when serializing CSV data.
141#[derive(Debug, PartialEq, Eq)]
142pub enum Error {
143    /// Buffer overflow.
144    Overflow,
145}
146
147/// Alias for a `core::result::Result` with the error type `serde_csv_core::ser::Error`.
148pub type Result<T> = core::result::Result<T, Error>;
149
150macro_rules! impl_format {
151    ($self:ident, $write:ident, $f:ident) => {
152        match $self {
153            Self::Overflow => $write!($f, "Buffer overflow"),
154        }
155    };
156}
157
158impl core::fmt::Display for Error {
159    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
160        impl_format!(self, write, f)
161    }
162}
163
164impl serde::ser::StdError for Error {}
165
166impl serde::ser::Error for Error {
167    fn custom<T>(_msg: T) -> Self
168    where
169        T: core::fmt::Display,
170    {
171        unimplemented!("custom is not supported")
172    }
173}
174
175#[cfg(feature = "defmt")]
176impl defmt::Format for Error {
177    fn format(&self, f: defmt::Formatter) {
178        use defmt::write;
179        impl_format!(self, write, f)
180    }
181}
182
183/// A structure for serializing Rust values into CSV.
184#[derive(Debug)]
185pub struct Serializer<'a> {
186    writer: &'a mut csv_core::Writer,
187    output: &'a mut [u8],
188    nwritten: usize,
189}
190
191impl<'a> Serializer<'a> {
192    /// Creates a new CSV serializer.
193    pub fn new(writer: &'a mut csv_core::Writer, output: &'a mut [u8]) -> Self {
194        Self {
195            writer,
196            output,
197            nwritten: 0,
198        }
199    }
200
201    /// Returns the number of bytes written.
202    pub fn bytes_written(&self) -> usize {
203        self.nwritten
204    }
205
206    fn field(&mut self, input: impl AsRef<[u8]>) -> Result<()> {
207        let (r, _, n) = self
208            .writer
209            .field(input.as_ref(), &mut self.output[self.nwritten..]);
210        self.nwritten += n;
211        if r == csv_core::WriteResult::OutputFull {
212            return Err(Error::Overflow);
213        }
214        Ok(())
215    }
216
217    fn delimiter(&mut self) -> Result<()> {
218        let (r, n) = self.writer.delimiter(&mut self.output[self.nwritten..]);
219        self.nwritten += n;
220        if r == csv_core::WriteResult::OutputFull {
221            return Err(Error::Overflow);
222        }
223        Ok(())
224    }
225}
226
227impl<'a, 'b> ser::Serializer for &'a mut Serializer<'b> {
228    type Ok = ();
229
230    type Error = Error;
231
232    type SerializeSeq = Compound<'a, 'b>;
233
234    type SerializeTuple = Compound<'a, 'b>;
235
236    type SerializeTupleStruct = Compound<'a, 'b>;
237
238    type SerializeTupleVariant = Unreachable;
239
240    type SerializeMap = Unreachable;
241
242    type SerializeStruct = Compound<'a, 'b>;
243
244    type SerializeStructVariant = Unreachable;
245
246    fn serialize_bool(self, v: bool) -> Result<Self::Ok> {
247        if v {
248            self.field(b"true")
249        } else {
250            self.field(b"false")
251        }
252    }
253
254    fn serialize_i8(self, v: i8) -> Result<Self::Ok> {
255        let mut buffer = itoa::Buffer::new();
256        self.field(buffer.format(v))
257    }
258
259    fn serialize_i16(self, v: i16) -> Result<Self::Ok> {
260        let mut buffer = itoa::Buffer::new();
261        self.field(buffer.format(v))
262    }
263
264    fn serialize_i32(self, v: i32) -> Result<Self::Ok> {
265        let mut buffer = itoa::Buffer::new();
266        self.field(buffer.format(v))
267    }
268
269    fn serialize_i64(self, v: i64) -> Result<Self::Ok> {
270        let mut buffer = itoa::Buffer::new();
271        self.field(buffer.format(v))
272    }
273
274    fn serialize_u8(self, v: u8) -> Result<Self::Ok> {
275        let mut buffer = itoa::Buffer::new();
276        self.field(buffer.format(v))
277    }
278
279    fn serialize_u16(self, v: u16) -> Result<Self::Ok> {
280        let mut buffer = itoa::Buffer::new();
281        self.field(buffer.format(v))
282    }
283
284    fn serialize_u32(self, v: u32) -> Result<Self::Ok> {
285        let mut buffer = itoa::Buffer::new();
286        self.field(buffer.format(v))
287    }
288
289    fn serialize_u64(self, v: u64) -> Result<Self::Ok> {
290        let mut buffer = itoa::Buffer::new();
291        self.field(buffer.format(v))
292    }
293
294    fn serialize_f32(self, v: f32) -> Result<Self::Ok> {
295        let mut buffer = ryu::Buffer::new();
296        self.field(buffer.format(v))
297    }
298
299    fn serialize_f64(self, v: f64) -> Result<Self::Ok> {
300        let mut buffer = ryu::Buffer::new();
301        self.field(buffer.format(v))
302    }
303
304    fn serialize_char(self, v: char) -> Result<Self::Ok> {
305        self.field(v.encode_utf8(&mut [0; 4]))
306    }
307
308    fn serialize_str(self, v: &str) -> Result<Self::Ok> {
309        self.field(v)
310    }
311
312    fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok> {
313        self.field(v)
314    }
315
316    fn serialize_none(self) -> Result<Self::Ok> {
317        self.field([])
318    }
319
320    fn serialize_some<T>(self, value: &T) -> Result<Self::Ok>
321    where
322        T: ser::Serialize + ?Sized,
323    {
324        value.serialize(self)
325    }
326
327    fn serialize_unit(self) -> Result<Self::Ok> {
328        self.field([])
329    }
330
331    fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok> {
332        self.field(name)
333    }
334
335    fn serialize_unit_variant(
336        self,
337        _name: &'static str,
338        _variant_index: u32,
339        variant: &'static str,
340    ) -> Result<Self::Ok> {
341        self.field(variant)
342    }
343
344    fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<Self::Ok>
345    where
346        T: ser::Serialize + ?Sized,
347    {
348        value.serialize(self)
349    }
350
351    fn serialize_newtype_variant<T>(
352        self,
353        _name: &'static str,
354        _variant_index: u32,
355        _variant: &'static str,
356        _value: &T,
357    ) -> Result<Self::Ok>
358    where
359        T: ser::Serialize + ?Sized,
360    {
361        unimplemented!("`Serializer::serialize_newtype_variant` is not supported");
362    }
363
364    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
365        Ok(Compound::new(self))
366    }
367
368    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
369        Ok(Compound::new(self))
370    }
371
372    fn serialize_tuple_struct(
373        self,
374        _name: &'static str,
375        _len: usize,
376    ) -> Result<Self::SerializeTupleStruct> {
377        Ok(Compound::new(self))
378    }
379
380    fn serialize_tuple_variant(
381        self,
382        _name: &'static str,
383        _variant_index: u32,
384        _variant: &'static str,
385        _len: usize,
386    ) -> Result<Self::SerializeTupleVariant> {
387        unimplemented!("`Serializer::serialize_tuple_variant` is not supported");
388    }
389
390    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
391        unimplemented!("`Serializer::serialize_map` is not supported");
392    }
393
394    fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
395        Ok(Compound::new(self))
396    }
397
398    fn serialize_struct_variant(
399        self,
400        _name: &'static str,
401        _variant_index: u32,
402        _variant: &'static str,
403        _len: usize,
404    ) -> Result<Self::SerializeStructVariant> {
405        unimplemented!("`Serializer::serialize_struct_variant` is not supported");
406    }
407
408    fn collect_str<T>(self, _value: &T) -> Result<Self::Ok>
409    where
410        T: core::fmt::Display + ?Sized,
411    {
412        unimplemented!("`Serializer::collect_str` is not supported");
413    }
414}
415
416#[doc(hidden)]
417pub struct Compound<'a, 'b> {
418    serializer: &'a mut Serializer<'b>,
419    nfields: usize,
420}
421
422impl<'a, 'b> Compound<'a, 'b> {
423    fn new(serializer: &'a mut Serializer<'b>) -> Self {
424        Self {
425            serializer,
426            nfields: 0,
427        }
428    }
429
430    fn element<T>(&mut self, value: &T) -> Result<()>
431    where
432        T: ser::Serialize + ?Sized,
433    {
434        if self.nfields > 0 {
435            self.serializer.delimiter()?;
436        }
437        self.nfields += 1;
438        value.serialize(&mut *self.serializer)
439    }
440}
441
442impl ser::SerializeSeq for Compound<'_, '_> {
443    type Ok = ();
444
445    type Error = Error;
446
447    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
448    where
449        T: ser::Serialize + ?Sized,
450    {
451        self.element(value)
452    }
453
454    fn end(self) -> Result<Self::Ok> {
455        Ok(())
456    }
457}
458
459impl ser::SerializeTuple for Compound<'_, '_> {
460    type Ok = ();
461
462    type Error = Error;
463
464    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
465    where
466        T: ser::Serialize + ?Sized,
467    {
468        self.element(value)
469    }
470
471    fn end(self) -> Result<Self::Ok> {
472        Ok(())
473    }
474}
475
476impl ser::SerializeTupleStruct for Compound<'_, '_> {
477    type Ok = ();
478
479    type Error = Error;
480
481    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
482    where
483        T: ser::Serialize + ?Sized,
484    {
485        self.element(value)
486    }
487
488    fn end(self) -> Result<Self::Ok> {
489        Ok(())
490    }
491}
492
493impl ser::SerializeStruct for Compound<'_, '_> {
494    type Ok = ();
495
496    type Error = Error;
497
498    fn serialize_field<T>(&mut self, _key: &'static str, value: &T) -> Result<()>
499    where
500        T: ser::Serialize + ?Sized,
501    {
502        self.element(value)
503    }
504
505    fn end(self) -> Result<Self::Ok> {
506        Ok(())
507    }
508}
509
510#[doc(hidden)]
511pub struct Unreachable;
512
513impl ser::SerializeTupleVariant for Unreachable {
514    type Ok = ();
515
516    type Error = Error;
517
518    fn serialize_field<T>(&mut self, _value: &T) -> Result<()>
519    where
520        T: ser::Serialize + ?Sized,
521    {
522        unreachable!()
523    }
524
525    fn end(self) -> Result<Self::Ok> {
526        unreachable!()
527    }
528}
529
530impl ser::SerializeMap for Unreachable {
531    type Ok = ();
532
533    type Error = Error;
534
535    fn serialize_key<T>(&mut self, _key: &T) -> Result<()>
536    where
537        T: ser::Serialize + ?Sized,
538    {
539        unreachable!()
540    }
541
542    fn serialize_value<T>(&mut self, _value: &T) -> Result<()>
543    where
544        T: ser::Serialize + ?Sized,
545    {
546        unreachable!()
547    }
548
549    fn end(self) -> Result<Self::Ok> {
550        unreachable!()
551    }
552}
553
554impl ser::SerializeStructVariant for Unreachable {
555    type Ok = ();
556
557    type Error = Error;
558
559    fn serialize_field<T>(&mut self, _key: &'static str, _value: &T) -> Result<()>
560    where
561        T: ser::Serialize + ?Sized,
562    {
563        unreachable!()
564    }
565
566    fn end(self) -> Result<Self::Ok> {
567        unreachable!()
568    }
569}