Skip to main content

deser_csv/
de.rs

1use alloc::format;
2use alloc::string::String;
3use alloc::string::ToString;
4use alloc::sync::Arc;
5use alloc::vec::Vec;
6use core::marker::PhantomData;
7
8use deser_core::__format::{MakeSink, deserialize_value, drive_value};
9use deser_core::Text;
10use deser_core::de::{self, Deserialize, DeserializeDriver, Frame, LexicalRules};
11use deser_core::{Atom, Bytes, BytesFormat, ContainerShape, Error, ErrorKind, Event, Source};
12
13use crate::parser::{Dialect, Field, Options, QUOTED, Scan, Scanner, UNESCAPE, unescape};
14use crate::{Escape, Headers, Nulls, Terminator, Trim};
15
16/// Configures how delimited text is deserialized.
17///
18/// The configuration is independent of the input so it can be created once
19/// (even as a constant) and used for many inputs.  The methods
20/// [`from_str`](Self::from_str) and [`from_slice`](Self::from_slice) work
21/// like the functions of the same name.  The default is CSV as described
22/// by [RFC 4180](https://www.rfc-editor.org/rfc/rfc4180), with a header,
23/// any line ending and blank lines skipped.
24///
25/// ```
26/// use deser_csv::DeserializerConfig;
27///
28/// const SEMICOLONS: DeserializerConfig =
29///     DeserializerConfig::new().delimiter(b';');
30/// let rows: Vec<(String, u32)> = SEMICOLONS
31///     .headers(deser_csv::Headers::None)
32///     .from_str("a;1\nb;2\n")
33///     .unwrap();
34/// assert_eq!(rows, [("a".into(), 1), ("b".into(), 2)]);
35/// ```
36#[derive(Debug, Clone, PartialEq, Eq)]
37pub struct DeserializerConfig {
38    pub(crate) delimiter: u8,
39    pub(crate) quote: Option<u8>,
40    pub(crate) double_quote: bool,
41    pub(crate) escape: Escape,
42    pub(crate) terminator: Terminator,
43    pub(crate) comment: Option<u8>,
44    pub(crate) headers: Headers,
45    pub(crate) trim: Trim,
46    pub(crate) nulls: Nulls,
47    pub(crate) skip_blank_lines: bool,
48    pub(crate) flexible: bool,
49    pub(crate) lenient_quotes: bool,
50    pub(crate) sep_line: bool,
51    pub(crate) max_record_len: usize,
52    pub(crate) bytes: BytesFormat,
53    pub(crate) track_locations: bool,
54}
55
56impl Default for DeserializerConfig {
57    fn default() -> DeserializerConfig {
58        DeserializerConfig::new()
59    }
60}
61
62impl DeserializerConfig {
63    /// Creates the default configuration (CSV).
64    pub const fn new() -> DeserializerConfig {
65        DeserializerConfig {
66            delimiter: b',',
67            quote: Some(b'"'),
68            double_quote: true,
69            escape: Escape::None,
70            terminator: Terminator::Newline,
71            comment: None,
72            headers: Headers::First,
73            trim: Trim::None,
74            nulls: Nulls::None,
75            skip_blank_lines: true,
76            flexible: false,
77            lenient_quotes: false,
78            sep_line: false,
79            max_record_len: 64 * 1024 * 1024,
80            bytes: BytesFormat::BASE64,
81            track_locations: false,
82        }
83    }
84
85    /// Creates the configuration for tab separated values.
86    ///
87    /// Fields are separated by tabs and are not quoted.  Tabs, line breaks
88    /// and backslashes in fields are escaped with backslashes (`\t`, `\n`,
89    /// `\r` and `\\`) and `\N` is null (see [`Escape::Backslash`] and
90    /// [`Nulls::Text`]).  This is how databases (like PostgreSQL's `COPY`
91    /// and MySQL's `LOAD DATA`) and many tools write TSV, and it reads the
92    /// TSV of [IANA](https://www.iana.org/assignments/media-types/text/tab-separated-values)
93    /// (which cannot contain tabs and line breaks in fields) as well.  For
94    /// TSV with quotes (as written by spreadsheets) use
95    /// `DeserializerConfig::new().delimiter(b'\t')`.
96    ///
97    /// ```
98    /// use deser_csv::DeserializerConfig;
99    ///
100    /// #[derive(deser::Deserialize)]
101    /// struct Row {
102    ///     name: String,
103    ///     note: Option<String>,
104    /// }
105    ///
106    /// let rows: Vec<Row> = DeserializerConfig::tsv()
107    ///     .from_str("name\tnote\nJane\ta\\tb\nJohn\t\\N\n")
108    ///     .unwrap();
109    /// assert_eq!(rows[0].note.as_deref(), Some("a\tb"));
110    /// assert_eq!(rows[1].note, None);
111    /// ```
112    pub const fn tsv() -> DeserializerConfig {
113        DeserializerConfig::new()
114            .delimiter(b'\t')
115            .quote(None)
116            .escape(Escape::Backslash)
117            .nulls(Nulls::Text("\\N"))
118    }
119
120    /// Sets the character that separates fields (`,` by default).
121    ///
122    /// Special characters (the delimiter, quote, escape and terminator)
123    /// have to be distinct ASCII characters, otherwise deserializing fails.
124    pub const fn delimiter(mut self, delimiter: u8) -> DeserializerConfig {
125        self.delimiter = delimiter;
126        self
127    }
128
129    /// Sets the character that quotes fields (`"` by default).
130    ///
131    /// Quoted fields can contain the delimiter and line breaks.  With
132    /// `None` quotes are regular characters.
133    pub const fn quote(mut self, quote: Option<u8>) -> DeserializerConfig {
134        self.quote = quote;
135        self
136    }
137
138    /// Sets if two quotes in a quoted field are a quote (`true` by
139    /// default).
140    ///
141    /// Without doubled quotes, quotes in quoted fields have to be escaped
142    /// (see [`escape`](Self::escape)).
143    pub const fn double_quote(mut self, yes: bool) -> DeserializerConfig {
144        self.double_quote = yes;
145        self
146    }
147
148    /// Sets how characters are escaped (not at all by default).
149    pub const fn escape(mut self, escape: Escape) -> DeserializerConfig {
150        self.escape = escape;
151        self
152    }
153
154    /// Sets what ends records ([`Terminator::Newline`] by default).
155    pub const fn terminator(mut self, terminator: Terminator) -> DeserializerConfig {
156        self.terminator = terminator;
157        self
158    }
159
160    /// Sets the character that starts comment lines (none by default).
161    ///
162    /// Lines that start with it are skipped.  The character only starts a
163    /// comment at the start of a line (`a,#b` is a regular record).
164    pub const fn comment(mut self, comment: Option<u8>) -> DeserializerConfig {
165        self.comment = comment;
166        self
167    }
168
169    /// Sets where the names of the columns come from ([`Headers::First`] by
170    /// default).
171    ///
172    /// With names, records are maps of the names to the fields.  Without
173    /// names ([`Headers::None`]) records are sequences.
174    pub const fn headers(mut self, headers: Headers) -> DeserializerConfig {
175        self.headers = headers;
176        self
177    }
178
179    /// Sets which whitespace is removed ([`Trim::None`] by default).
180    ///
181    /// Spaces and tabs are removed from the start and end of unquoted
182    /// fields and around the quotes of quoted fields (`a, "b" ,c`).
183    pub const fn trim(mut self, trim: Trim) -> DeserializerConfig {
184        self.trim = trim;
185        self
186    }
187
188    /// Sets which fields are null ([`Nulls::None`] by default).
189    ///
190    /// Without nulls, empty fields are `None` for optionals of types that
191    /// do not accept the empty string (like `Option<u32>`) and `Some("")`
192    /// for strings.  Quoted fields are never null.
193    pub const fn nulls(mut self, nulls: Nulls) -> DeserializerConfig {
194        self.nulls = nulls;
195        self
196    }
197
198    /// Sets if blank lines are skipped (`true` by default).
199    ///
200    /// Otherwise a blank line is a record with a single empty field.  Lines
201    /// with only whitespace are not blank.
202    pub const fn skip_blank_lines(mut self, yes: bool) -> DeserializerConfig {
203        self.skip_blank_lines = yes;
204        self
205    }
206
207    /// Sets if records can have a different number of fields (`false` by
208    /// default).
209    ///
210    /// By default, records must have as many fields as there are columns
211    /// (or as the first record has, without names).  With flexible records,
212    /// missing fields are missing in the map and fields without names are
213    /// keyed with their index (`"3"`), so they end up in a flattened map
214    /// or are ignored like unknown fields.
215    pub const fn flexible(mut self, yes: bool) -> DeserializerConfig {
216        self.flexible = yes;
217        self
218    }
219
220    /// Sets if quotes that do not follow the rules are accepted (`false` by
221    /// default).
222    ///
223    /// By default, quotes in unquoted fields (`5'10"`) and characters after
224    /// the closing quote of a field (`"a"b`) are errors.  With lenient
225    /// quotes the quotes of unquoted fields are regular characters and
226    /// characters after the closing quote are part of the field (`ab`).
227    pub const fn lenient_quotes(mut self, yes: bool) -> DeserializerConfig {
228        self.lenient_quotes = yes;
229        self
230    }
231
232    /// Sets if a `sep=` line at the start selects the delimiter (`false` by
233    /// default).
234    ///
235    /// Excel writes and understands a first line like `sep=;` which sets
236    /// the delimiter of the file.
237    ///
238    /// ```
239    /// use std::collections::BTreeMap;
240    ///
241    /// let config = deser_csv::DeserializerConfig::new().sep_line(true);
242    /// let rows: Vec<BTreeMap<String, u32>> =
243    ///     config.from_str("sep=;\na;b\n1;2\n").unwrap();
244    /// assert_eq!(rows[0]["b"], 2);
245    /// ```
246    pub const fn sep_line(mut self, yes: bool) -> DeserializerConfig {
247        self.sep_line = yes;
248        self
249    }
250
251    /// Sets the maximum length of a record in a stream in bytes (64 MiB by
252    /// default).
253    ///
254    /// A record in a stream is buffered until it's complete.  A longer
255    /// record is an error which ends the stream, which protects from
256    /// streams that never end a record (like a quoted field that is never
257    /// closed).  Inputs in memory are not limited.
258    pub const fn max_record_len(mut self, len: usize) -> DeserializerConfig {
259        self.max_record_len = len;
260        self
261    }
262
263    /// Sets how fields are decoded into bytes.
264    ///
265    /// Types that expect bytes (like `Vec<u8>`) decode fields as base64 by
266    /// default.  Fields which are not UTF-8 are passed on as bytes (see
267    /// [bytes](deser_core::adapters#bytes)).
268    pub const fn bytes(mut self, format: BytesFormat) -> DeserializerConfig {
269        self.bytes = format;
270        self
271    }
272
273    /// Enables or disables location tracking.
274    ///
275    /// The byte range of every field is always published into the state
276    /// (see [`State::input_range`](deser_core::State::input_range)).  When
277    /// enabled additionally the input is set as source (see
278    /// [`Source`](deser_core::Source)).  This copies the input.
279    pub const fn track_locations(mut self, yes: bool) -> DeserializerConfig {
280        self.track_locations = yes;
281        self
282    }
283
284    /// Deserializes the records of a string.
285    ///
286    /// See [`from_str`](crate::from_str).
287    pub fn from_str<'de, T: Deserialize<'de>>(&self, s: &'de str) -> Result<T, Error> {
288        deserialize_value(|make_sink| self.drive_str(s, make_sink))
289    }
290
291    /// The part of [`from_str`](Self::from_str) that does not depend on the type
292    /// of the value, it exists once.
293    fn drive_str<'de>(
294        &self,
295        s: &'de str,
296        make_sink: &mut MakeSink<'_, '_, 'de>,
297    ) -> Result<(), Error> {
298        drive_value(&mut Deserializer::from_str_with_config(s, self), make_sink)
299    }
300
301    /// Deserializes the records of a byte slice.
302    ///
303    /// See [`from_slice`](crate::from_slice).
304    pub fn from_slice<'de, T: Deserialize<'de>>(&self, bytes: &'de [u8]) -> Result<T, Error> {
305        deserialize_value(|make_sink| self.drive_slice(bytes, make_sink))
306    }
307
308    /// The part of [`from_slice`](Self::from_slice) that does not depend on the type
309    /// of the value, it exists once.
310    fn drive_slice<'de>(
311        &self,
312        bytes: &'de [u8],
313        make_sink: &mut MakeSink<'_, '_, 'de>,
314    ) -> Result<(), Error> {
315        drive_value(
316            &mut Deserializer::from_slice_with_config(bytes, self),
317            make_sink,
318        )
319    }
320
321    /// Returns how records are scanned.
322    fn options(&self, header: bool) -> Options {
323        Options {
324            trim: match self.trim {
325                Trim::None => false,
326                Trim::Headers => header,
327                Trim::Fields => !header,
328                Trim::All => true,
329            },
330            skip_blank_lines: self.skip_blank_lines,
331            lenient_quotes: self.lenient_quotes,
332            max_record_len: self.max_record_len,
333        }
334    }
335
336    fn dialect(&self, delimiter: u8) -> Result<Dialect, Error> {
337        Dialect::new(
338            delimiter,
339            self.quote,
340            self.double_quote,
341            self.escape,
342            self.terminator,
343            self.comment,
344        )
345    }
346}
347
348/// The state of a stream of records.
349///
350/// This holds the names of the columns and what is needed to split the
351/// records.
352#[derive(Debug, Default)]
353pub(crate) struct StreamState {
354    // `None` before the start of the stream (BOM and `sep=` line) was read
355    dialect: Option<Dialect>,
356    scanner: Scanner,
357    names: Option<Vec<String>>,
358    // the names were read (or given, or there are none)
359    has_names: bool,
360    // the number of fields of the first record (without names)
361    expected_len: Option<usize>,
362    // decoded fields and names
363    scratch: Vec<u8>,
364}
365
366impl StreamState {
367    /// Creates the state of a stream which continues with the given names
368    /// of the columns.
369    pub(crate) fn with_headers(names: Vec<String>) -> StreamState {
370        StreamState {
371            names: Some(names),
372            has_names: true,
373            ..StreamState::default()
374        }
375    }
376
377    /// Returns the names of the columns.
378    pub(crate) fn headers(&self) -> Option<&[String]> {
379        self.names.as_deref()
380    }
381
382    /// Finds the next record.
383    ///
384    /// This works like
385    /// [`StreamDeserializer::frame`](deser_core::de::StreamDeserializer::frame).
386    /// Blank lines, comments and names are consumed without returning a
387    /// record.  The fields of the record are kept in the scanner.
388    pub(crate) fn frame(
389        &mut self,
390        config: &DeserializerConfig,
391        input: &[u8],
392        eof: bool,
393    ) -> Result<Frame, Error> {
394        if self.dialect.is_none() {
395            match self.start(config, input, eof)? {
396                Frame::Incomplete { consumed: 0 } if self.dialect.is_some() => {}
397                frame => return Ok(frame),
398            }
399        }
400        let dialect = self.dialect.as_ref().unwrap();
401        let header = !self.has_names;
402        let options = config.options(header);
403        match self.scanner.scan(dialect, input, eof, options)? {
404            Scan::Record { end, consumed } => {
405                if header {
406                    self.read_names(input)?;
407                    return Ok(Frame::Incomplete { consumed });
408                }
409                if self.names.is_none() && self.expected_len.is_none() {
410                    self.expected_len = Some(self.scanner.fields.len());
411                }
412                Ok(Frame::Value {
413                    start: 0,
414                    end,
415                    consumed,
416                })
417            }
418            Scan::Skip { consumed } => Ok(Frame::Incomplete { consumed }),
419            Scan::Incomplete => Ok(Frame::Incomplete { consumed: 0 }),
420            Scan::End => Ok(Frame::End),
421        }
422    }
423
424    /// Reads the start of the stream: the byte order mark and the `sep=`
425    /// line.
426    fn start(
427        &mut self,
428        config: &DeserializerConfig,
429        input: &[u8],
430        eof: bool,
431    ) -> Result<Frame, Error> {
432        const BOM: &[u8] = b"\xef\xbb\xbf";
433        const SEP: &[u8] = b"sep=";
434        if input.len() < BOM.len() && BOM.starts_with(input) && !eof {
435            return Ok(Frame::Incomplete { consumed: 0 });
436        }
437        if input.starts_with(b"\xff\xfe") || input.starts_with(b"\xfe\xff") {
438            return Err(Error::new(
439                ErrorKind::Unexpected,
440                "input is UTF-16, only UTF-8 is supported",
441            )
442            .with_offset(0));
443        }
444        let bom = if input.starts_with(BOM) { BOM.len() } else { 0 };
445        let rest = &input[bom..];
446        let prefix = rest.len().min(SEP.len());
447        if !config.sep_line || !rest[..prefix].eq_ignore_ascii_case(&SEP[..prefix]) {
448            return self.started(config, config.delimiter, bom);
449        }
450        // wait for the whole line (and the LF after a CR)
451        let end = match rest.iter().position(|&b| b == b'\n' || b == b'\r') {
452            Some(end) if rest[end] == b'\r' && end + 1 == rest.len() && !eof => {
453                return Ok(Frame::Incomplete { consumed: 0 });
454            }
455            Some(end) => end,
456            None if eof => rest.len(),
457            None => return Ok(Frame::Incomplete { consumed: 0 }),
458        };
459        if end != SEP.len() + 1 {
460            return self.started(config, config.delimiter, bom);
461        }
462        let mut consumed = bom + end + 1;
463        if rest.get(end) == Some(&b'\r') && rest.get(end + 1) == Some(&b'\n') {
464            consumed += 1;
465        }
466        self.started(config, rest[SEP.len()], consumed.min(input.len()))
467    }
468
469    fn started(
470        &mut self,
471        config: &DeserializerConfig,
472        delimiter: u8,
473        consumed: usize,
474    ) -> Result<Frame, Error> {
475        self.dialect = Some(config.dialect(delimiter)?);
476        if !self.has_names {
477            match config.headers {
478                Headers::First | Headers::Skip => {}
479                Headers::None => self.has_names = true,
480                Headers::Given(names) => {
481                    self.names = Some(names.iter().map(|name| name.to_string()).collect());
482                    self.has_names = true;
483                }
484            }
485        }
486        Ok(Frame::Incomplete { consumed })
487    }
488
489    /// Takes the names of the columns from the record that was scanned.
490    fn read_names(&mut self, record: &[u8]) -> Result<(), Error> {
491        if let Some((offset, msg)) = self.scanner.error {
492            return Err(Error::new(ErrorKind::Unexpected, msg).with_offset(offset));
493        }
494        let dialect = self.dialect.as_ref().unwrap();
495        let mut names = Vec::with_capacity(self.scanner.fields.len());
496        for field in &self.scanner.fields {
497            let text = &record[field.start..field.end];
498            let text = if field.flags & UNESCAPE != 0 {
499                unescape(dialect, text, field.flags & QUOTED != 0, &mut self.scratch);
500                &self.scratch[..]
501            } else {
502                text
503            };
504            match core::str::from_utf8(text) {
505                Ok(name) => names.push(name.to_string()),
506                Err(_) => {
507                    return Err(Error::new(ErrorKind::Unexpected, "name is not valid UTF-8")
508                        .with_offset(field.span_start));
509                }
510            }
511        }
512        self.names = Some(names);
513        self.has_names = true;
514        Ok(())
515    }
516
517    /// Emits the record that was found last.
518    ///
519    /// `record` holds the bytes of the record, `base` is its offset in the
520    /// input for the input ranges.
521    pub(crate) fn emit_record<'de>(
522        &mut self,
523        config: &DeserializerConfig,
524        record: &'de [u8],
525        base: usize,
526        driver: &mut DeserializeDriver<'_, 'de>,
527    ) -> Result<(), Error> {
528        let StreamState {
529            ref dialect,
530            ref scanner,
531            ref names,
532            expected_len,
533            ref mut scratch,
534            ..
535        } = *self;
536        let self_names_len = names.as_ref().map(Vec::len);
537        let dialect = dialect
538            .as_ref()
539            .expect("records are emitted after the start");
540        if let Some((offset, msg)) = scanner.error {
541            return Err(Error::new(ErrorKind::Unexpected, msg).with_offset(base + offset));
542        }
543        if config.bytes != BytesFormat::BASE64 {
544            config.bytes.set(driver.state_mut());
545        }
546        // everything in a CSV file is text, like in a query string
547        LexicalRules::LENIENT.set(driver.state_mut());
548        let fields = &scanner.fields[..];
549        // with `Headers::Skip` the names are known but not used
550        let names = match config.headers {
551            Headers::Skip => None,
552            _ => names.as_ref(),
553        };
554        let expected = match (names, self_names_len) {
555            (Some(names), _) => names.len(),
556            (None, Some(len)) => len,
557            (None, None) => expected_len.unwrap_or(fields.len()),
558        };
559        if fields.len() != expected && !config.flexible {
560            return Err(Error::new(
561                ErrorKind::Unexpected,
562                format!(
563                    "record has {} field{}, expected {}",
564                    fields.len(),
565                    if fields.len() == 1 { "" } else { "s" },
566                    expected
567                ),
568            )
569            .with_offset(base));
570        }
571
572        let shape = ContainerShape::new().with_len(fields.len());
573        let emitter = FieldEmitter {
574            dialect,
575            nulls: config.nulls,
576            record,
577            // the special characters are ASCII, so if the record is UTF-8
578            // all of its fields are
579            record_is_utf8: record.is_ascii() || core::str::from_utf8(record).is_ok(),
580            base,
581        };
582        // the start and end of the record are at its start and end (for
583        // errors like missing fields)
584        let end = base + record.len();
585        driver.state_mut().set_input_range(base, base);
586        match names {
587            Some(names) => {
588                // header names can repeat: records are multimaps
589                driver.emit(Event::MapStart(shape.with_multimap(true)))?;
590                for (index, field) in fields.iter().enumerate() {
591                    emitter.set_range(driver, field);
592                    match names.get(index) {
593                        // the names are only valid for this call, sinks
594                        // that keep them copy them
595                        Some(name) => driver.emit(Atom::Lexical(Text::borrowed(name.as_str())))?,
596                        None => driver.emit(Atom::Lexical(Text::owned(index.to_string())))?,
597                    }
598                    emitter.emit(driver, field, scratch)?;
599                }
600                driver.state_mut().set_input_range(end, end);
601                driver.emit(Event::MapEnd)
602            }
603            None => {
604                driver.emit(Event::SeqStart(shape))?;
605                for field in fields {
606                    emitter.emit(driver, field, scratch)?;
607                }
608                driver.state_mut().set_input_range(end, end);
609                driver.emit(Event::SeqEnd)
610            }
611        }
612    }
613}
614
615/// Emits the fields of a record.
616struct FieldEmitter<'a, 'de> {
617    dialect: &'a Dialect,
618    nulls: Nulls,
619    record: &'de [u8],
620    record_is_utf8: bool,
621    base: usize,
622}
623
624impl<'de> FieldEmitter<'_, 'de> {
625    #[inline]
626    fn set_range(&self, driver: &mut DeserializeDriver<'_, 'de>, field: &Field) {
627        driver
628            .state_mut()
629            .set_input_range(self.base + field.span_start, self.base + field.span_end);
630    }
631
632    #[inline]
633    fn emit(
634        &self,
635        driver: &mut DeserializeDriver<'_, 'de>,
636        field: &Field,
637        scratch: &mut Vec<u8>,
638    ) -> Result<(), Error> {
639        self.set_range(driver, field);
640        let text = &self.record[field.start..field.end];
641        if field.flags & QUOTED == 0 {
642            match self.nulls {
643                Nulls::Empty if text.is_empty() => return driver.emit(Atom::Null),
644                Nulls::Text(null) if text == null.as_bytes() => return driver.emit(Atom::Null),
645                _ => {}
646            }
647        }
648        if field.flags & UNESCAPE != 0 {
649            unescape(self.dialect, text, field.flags & QUOTED != 0, scratch);
650            // the decoded text is only valid for the call
651            match core::str::from_utf8(scratch) {
652                Ok(text) => driver.emit(Atom::Lexical(Text::borrowed(text))),
653                Err(_) => driver.emit(Atom::Bytes(Bytes::borrowed(scratch))),
654            }
655        } else if self.record_is_utf8 {
656            // SAFETY: the record is UTF-8 and fields start and end at ASCII
657            // characters (or the start and end of the record)
658            let text = unsafe { core::str::from_utf8_unchecked(text) };
659            driver.emit_borrowed(Atom::Lexical(Text::borrowed(text)))
660        } else {
661            match core::str::from_utf8(text) {
662                Ok(text) => driver.emit_borrowed(Atom::Lexical(Text::borrowed(text))),
663                Err(_) => driver.emit_borrowed(Atom::Bytes(Bytes::borrowed(text))),
664            }
665        }
666    }
667}
668
669/// Deserializes delimited text.
670///
671/// Most of the time the [`from_str`](crate::from_str) and
672/// [`from_slice`](crate::from_slice) functions (or the methods of the same
673/// name on [`DeserializerConfig`]) are all that is needed: they deserialize
674/// all records as a sequence.  The deserializer can also read one record
675/// at a time (see [`records`](Self::records)) and configure the driver, for
676/// instance to add layers:
677///
678/// ```
679/// use deser_path::{Path, PathLayer};
680/// use deser_csv::Deserializer;
681///
682/// #[derive(Debug, deser::Deserialize)]
683/// struct Row {
684///     name: String,
685///     age: u32,
686/// }
687///
688/// let err = Deserializer::from_str("name,age\njane,42\njohn,x\n")
689///     .deserialize_with::<Vec<Row>, _>(|driver| {
690///         driver.push_layer(PathLayer::new())
691///     })
692///     .unwrap_err();
693/// assert_eq!(err.message(), "invalid value \"x\", expected u32");
694/// assert_eq!(err.attachment::<Path>().unwrap().to_string(), "[1].age");
695/// assert_eq!((err.line(), err.column()), (Some(3), Some(6)));
696/// ```
697pub struct Deserializer<'a> {
698    input: &'a [u8],
699    pos: usize,
700    config: DeserializerConfig,
701    state: StreamState,
702    failed: bool,
703    // the input as source (with `track_locations`)
704    source: Option<Arc<str>>,
705}
706
707impl<'a> Deserializer<'a> {
708    /// Creates a new deserializer for a string.
709    #[allow(clippy::should_implement_trait)]
710    pub fn from_str(input: &'a str) -> Deserializer<'a> {
711        Deserializer::from_slice_with_config(input.as_bytes(), &DeserializerConfig::new())
712    }
713
714    /// Creates a new deserializer for a string with the given configuration.
715    pub fn from_str_with_config(input: &'a str, config: &DeserializerConfig) -> Deserializer<'a> {
716        Deserializer::from_slice_with_config(input.as_bytes(), config)
717    }
718
719    /// Creates a new deserializer for a byte slice.
720    ///
721    /// Fields which are not UTF-8 are passed on as bytes.
722    pub fn from_slice(input: &'a [u8]) -> Deserializer<'a> {
723        Deserializer::from_slice_with_config(input, &DeserializerConfig::new())
724    }
725
726    /// Creates a new deserializer for a byte slice with the given
727    /// configuration.
728    pub fn from_slice_with_config(
729        input: &'a [u8],
730        config: &DeserializerConfig,
731    ) -> Deserializer<'a> {
732        Deserializer {
733            input,
734            pos: 0,
735            config: config.clone(),
736            state: StreamState::default(),
737            failed: false,
738            source: None,
739        }
740    }
741
742    /// Returns the configuration.
743    pub fn config(&self) -> &DeserializerConfig {
744        &self.config
745    }
746
747    /// Returns the names of the columns.
748    ///
749    /// They are read with the first record.
750    pub fn headers(&self) -> Option<&[String]> {
751        self.state.headers()
752    }
753
754    /// Returns `true` if there are no more records.
755    ///
756    /// This is also the case after an error that the input cannot recover
757    /// from.  Blank lines and comments are not records, but they are only
758    /// skipped when the next record is read.
759    pub fn is_end(&self) -> bool {
760        self.failed || self.pos == self.input.len()
761    }
762
763    /// Deserializes all records as a sequence.
764    ///
765    /// To configure the deserialization (for instance to add layers) use
766    /// [`deserialize_with`](Self::deserialize_with).
767    pub fn deserialize<T: Deserialize<'a>>(&mut self) -> Result<T, Error> {
768        de::Deserializer::deserialize(self)
769    }
770
771    /// Deserializes all records as a sequence with a configured driver.
772    ///
773    /// The callback is invoked with the driver before the value is
774    /// deserialized, for instance to add [`Layer`](deser_core::de::Layer)s.
775    pub fn deserialize_with<T, F>(&mut self, setup: F) -> Result<T, Error>
776    where
777        T: Deserialize<'a>,
778        F: FnOnce(&mut DeserializeDriver<'_, 'a>),
779    {
780        de::Deserializer::deserialize_with(self, setup)
781    }
782
783    /// Deserializes the next record.
784    ///
785    /// Returns `None` if there are no more records.  Errors of a record
786    /// (like a field that does not fit the type) only discard the record,
787    /// the next call continues with the next record.
788    ///
789    /// ```
790    /// #[derive(deser::Deserialize)]
791    /// struct Row {
792    ///     name: String,
793    ///     age: u32,
794    /// }
795    ///
796    /// let mut de = deser_csv::Deserializer::from_str(
797    ///     "name,age\njane,42\njohn,x\nmax,7\n",
798    /// );
799    /// assert_eq!(de.deserialize_record::<Row>().unwrap().unwrap().age, 42);
800    /// assert!(de.deserialize_record::<Row>().is_err());
801    /// assert_eq!(de.deserialize_record::<Row>().unwrap().unwrap().age, 7);
802    /// assert!(de.deserialize_record::<Row>().unwrap().is_none());
803    /// ```
804    pub fn deserialize_record<T: Deserialize<'a>>(&mut self) -> Result<Option<T>, Error> {
805        self.deserialize_record_with(|_| {})
806    }
807
808    /// Deserializes the next record with a configured driver.
809    ///
810    /// See [`deserialize_record`](Self::deserialize_record).
811    pub fn deserialize_record_with<T, F>(&mut self, setup: F) -> Result<Option<T>, Error>
812    where
813        T: Deserialize<'a>,
814        F: FnOnce(&mut DeserializeDriver<'_, 'a>),
815    {
816        let mut out = None;
817        {
818            let mut driver = DeserializeDriver::new(&mut out);
819            setup(&mut driver);
820            if !self.drive_record(&mut driver)? {
821                return Ok(None);
822            }
823        }
824        out.ok_or_else(|| Error::new(ErrorKind::EndOfFile, "empty record"))
825            .map(Some)
826    }
827
828    /// Returns an iterator over the remaining records.
829    ///
830    /// Errors of records are returned and the iteration continues with the
831    /// next record (see [`deserialize_record`](Self::deserialize_record)).
832    pub fn records<T: Deserialize<'a>>(&mut self) -> Records<'_, 'a, T> {
833        Records {
834            de: self,
835            _marker: PhantomData,
836        }
837    }
838
839    /// Feeds the events of the next record into the given driver.
840    ///
841    /// Returns `false` if there are no more records.
842    pub fn drive_record(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<bool, Error> {
843        let rv = self.drive_record_impl(driver);
844        rv.map_err(|err| err.resolve_position(self.input))
845    }
846
847    fn drive_record_impl(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<bool, Error> {
848        let Some((start, end)) = self.next_record()? else {
849            return Ok(false);
850        };
851        let input = self.input;
852        self.set_source(driver);
853        self.state
854            .emit_record(&self.config, &input[start..end], start, driver)?;
855        Ok(true)
856    }
857
858    /// Sets the input as source (with `track_locations`).
859    fn set_source(&mut self, driver: &mut DeserializeDriver<'_, 'a>) {
860        if self.config.track_locations {
861            let input = self.input;
862            let source = self
863                .source
864                .get_or_insert_with(|| String::from_utf8_lossy(input).into());
865            Source::set(driver.state_mut(), source.clone());
866        }
867    }
868
869    /// Finds the next record and returns its range.
870    fn next_record(&mut self) -> Result<Option<(usize, usize)>, Error> {
871        if self.failed {
872            return Ok(None);
873        }
874        loop {
875            let input = &self.input[self.pos..];
876            let frame = match self.state.frame(&self.config, input, true) {
877                Ok(frame) => frame,
878                Err(err) => {
879                    // errors of the structure end the input
880                    self.failed = true;
881                    return Err(err.shift_offset(self.pos));
882                }
883            };
884            match frame {
885                Frame::Value {
886                    start,
887                    end,
888                    consumed,
889                } => {
890                    let range = (self.pos + start, self.pos + end);
891                    self.pos += consumed;
892                    return Ok(Some(range));
893                }
894                Frame::Incomplete { consumed } => self.pos += consumed,
895                Frame::End => return Ok(None),
896            }
897        }
898    }
899
900    /// Parses the input and feeds all records as a sequence into the given
901    /// driver.
902    ///
903    /// Fields that do not need to be decoded are passed on borrowed from
904    /// the input (see
905    /// [`emit_borrowed`](DeserializeDriver::emit_borrowed)).
906    pub fn drive(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
907        let rv = self.drive_impl(driver);
908        rv.map_err(|err| err.resolve_position(self.input))
909    }
910
911    fn drive_impl(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
912        self.set_source(driver);
913        let input = self.input;
914        driver.emit(Event::seq_start())?;
915        while let Some((start, end)) = self.next_record()? {
916            self.state
917                .emit_record(&self.config, &input[start..end], start, driver)?;
918        }
919        driver.emit(Event::SeqEnd)
920    }
921}
922
923impl<'a> de::Deserializer<'a> for Deserializer<'a> {
924    fn drive(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
925        Deserializer::drive(self, driver)
926    }
927}
928
929/// An iterator over the records of a [`Deserializer`].
930///
931/// See [`Deserializer::records`].
932pub struct Records<'d, 'a, T> {
933    de: &'d mut Deserializer<'a>,
934    _marker: PhantomData<fn() -> T>,
935}
936
937impl<'a, T: Deserialize<'a>> Iterator for Records<'_, 'a, T> {
938    type Item = Result<T, Error>;
939
940    fn next(&mut self) -> Option<Self::Item> {
941        self.de.deserialize_record().transpose()
942    }
943}
944
945/// Moves the offset of an error.
946trait ShiftOffset {
947    fn shift_offset(self, base: usize) -> Self;
948}
949
950impl ShiftOffset for Error {
951    fn shift_offset(self, base: usize) -> Error {
952        match self.offset() {
953            Some(offset) => self.with_offset(base + offset),
954            None => self,
955        }
956    }
957}