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