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#[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 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 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 pub const fn delimiter(mut self, delimiter: u8) -> DeserializerConfig {
125 self.delimiter = delimiter;
126 self
127 }
128
129 pub const fn quote(mut self, quote: Option<u8>) -> DeserializerConfig {
134 self.quote = quote;
135 self
136 }
137
138 pub const fn double_quote(mut self, yes: bool) -> DeserializerConfig {
144 self.double_quote = yes;
145 self
146 }
147
148 pub const fn escape(mut self, escape: Escape) -> DeserializerConfig {
150 self.escape = escape;
151 self
152 }
153
154 pub const fn terminator(mut self, terminator: Terminator) -> DeserializerConfig {
156 self.terminator = terminator;
157 self
158 }
159
160 pub const fn comment(mut self, comment: Option<u8>) -> DeserializerConfig {
165 self.comment = comment;
166 self
167 }
168
169 pub const fn headers(mut self, headers: Headers) -> DeserializerConfig {
175 self.headers = headers;
176 self
177 }
178
179 pub const fn trim(mut self, trim: Trim) -> DeserializerConfig {
184 self.trim = trim;
185 self
186 }
187
188 pub const fn nulls(mut self, nulls: Nulls) -> DeserializerConfig {
194 self.nulls = nulls;
195 self
196 }
197
198 pub const fn skip_blank_lines(mut self, yes: bool) -> DeserializerConfig {
203 self.skip_blank_lines = yes;
204 self
205 }
206
207 pub const fn flexible(mut self, yes: bool) -> DeserializerConfig {
216 self.flexible = yes;
217 self
218 }
219
220 pub const fn lenient_quotes(mut self, yes: bool) -> DeserializerConfig {
228 self.lenient_quotes = yes;
229 self
230 }
231
232 pub const fn sep_line(mut self, yes: bool) -> DeserializerConfig {
247 self.sep_line = yes;
248 self
249 }
250
251 pub const fn max_record_len(mut self, len: usize) -> DeserializerConfig {
259 self.max_record_len = len;
260 self
261 }
262
263 pub const fn bytes(mut self, format: BytesFormat) -> DeserializerConfig {
269 self.bytes = format;
270 self
271 }
272
273 pub const fn track_locations(mut self, yes: bool) -> DeserializerConfig {
280 self.track_locations = yes;
281 self
282 }
283
284 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 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 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 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 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#[derive(Debug, Default)]
353pub(crate) struct StreamState {
354 dialect: Option<Dialect>,
356 scanner: Scanner,
357 names: Option<Vec<String>>,
358 has_names: bool,
360 expected_len: Option<usize>,
362 scratch: Vec<u8>,
364}
365
366impl StreamState {
367 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 pub(crate) fn headers(&self) -> Option<&[String]> {
379 self.names.as_deref()
380 }
381
382 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 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 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 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 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 LexicalRules::LENIENT.set(driver.state_mut());
548 let fields = &scanner.fields[..];
549 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 record_is_utf8: record.is_ascii() || core::str::from_utf8(record).is_ok(),
580 base,
581 };
582 let end = base + record.len();
585 driver.state_mut().set_input_range(base, base);
586 match names {
587 Some(names) => {
588 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 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
615struct 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 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 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
669pub struct Deserializer<'a> {
698 input: &'a [u8],
699 pos: usize,
700 config: DeserializerConfig,
701 state: StreamState,
702 failed: bool,
703 source: Option<Arc<str>>,
705}
706
707impl<'a> Deserializer<'a> {
708 #[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 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 pub fn from_slice(input: &'a [u8]) -> Deserializer<'a> {
723 Deserializer::from_slice_with_config(input, &DeserializerConfig::new())
724 }
725
726 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 pub fn config(&self) -> &DeserializerConfig {
744 &self.config
745 }
746
747 pub fn headers(&self) -> Option<&[String]> {
751 self.state.headers()
752 }
753
754 pub fn is_end(&self) -> bool {
760 self.failed || self.pos == self.input.len()
761 }
762
763 pub fn deserialize<T: Deserialize<'a>>(&mut self) -> Result<T, Error> {
768 de::Deserializer::deserialize(self)
769 }
770
771 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 pub fn deserialize_record<T: Deserialize<'a>>(&mut self) -> Result<Option<T>, Error> {
805 self.deserialize_record_with(|_| {})
806 }
807
808 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 pub fn records<T: Deserialize<'a>>(&mut self) -> Records<'_, 'a, T> {
833 Records {
834 de: self,
835 _marker: PhantomData,
836 }
837 }
838
839 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 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 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 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 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
929pub 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
945trait 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}