1use alloc::format;
2use alloc::string::String;
3use alloc::string::ToString;
4use alloc::vec;
5use alloc::vec::Vec;
6use core::fmt::{self, Write as _};
7
8use deser_core::__format::{Float, IntBuffer, format_finite};
9use deser_core::ext::Number;
10use deser_core::ser::{self, PausableSink, SerializeDriver, Written};
11use deser_core::{Atom, BytesFormat, Error, ErrorKind, Event, Serialize, State};
12
13use crate::parser::Dialect;
14use crate::{Escape, Nulls, QuoteStyle, Terminator};
15
16#[derive(Debug, Clone, PartialEq, Eq)]
51pub struct SerializerConfig {
52 delimiter: u8,
53 quote: Option<u8>,
54 double_quote: bool,
55 escape: Escape,
56 terminator: Terminator,
57 quote_style: QuoteStyle,
58 headers: bool,
59 columns: Option<&'static [&'static str]>,
60 nulls: Nulls,
61 flexible: bool,
62 escape_formulas: bool,
63 bytes: BytesFormat,
64}
65
66impl Default for SerializerConfig {
67 fn default() -> SerializerConfig {
68 SerializerConfig::new()
69 }
70}
71
72impl SerializerConfig {
73 pub const fn new() -> SerializerConfig {
75 SerializerConfig {
76 delimiter: b',',
77 quote: Some(b'"'),
78 double_quote: true,
79 escape: Escape::None,
80 terminator: Terminator::Newline,
81 quote_style: QuoteStyle::Necessary,
82 headers: true,
83 columns: None,
84 nulls: Nulls::None,
85 flexible: false,
86 escape_formulas: false,
87 bytes: BytesFormat::BASE64,
88 }
89 }
90
91 pub const fn tsv() -> SerializerConfig {
104 SerializerConfig::new()
105 .delimiter(b'\t')
106 .quote(None)
107 .escape(Escape::Backslash)
108 .nulls(Nulls::Text("\\N"))
109 }
110
111 pub const fn delimiter(mut self, delimiter: u8) -> SerializerConfig {
113 self.delimiter = delimiter;
114 self
115 }
116
117 pub const fn quote(mut self, quote: Option<u8>) -> SerializerConfig {
122 self.quote = quote;
123 self
124 }
125
126 pub const fn double_quote(mut self, yes: bool) -> SerializerConfig {
130 self.double_quote = yes;
131 self
132 }
133
134 pub const fn escape(mut self, escape: Escape) -> SerializerConfig {
139 self.escape = escape;
140 self
141 }
142
143 pub const fn terminator(mut self, terminator: Terminator) -> SerializerConfig {
145 self.terminator = terminator;
146 self
147 }
148
149 pub const fn quote_style(mut self, style: QuoteStyle) -> SerializerConfig {
151 self.quote_style = style;
152 self
153 }
154
155 pub const fn headers(mut self, yes: bool) -> SerializerConfig {
162 self.headers = yes;
163 self
164 }
165
166 pub const fn columns(mut self, names: &'static [&'static str]) -> SerializerConfig {
193 self.columns = Some(names);
194 self
195 }
196
197 pub const fn nulls(mut self, nulls: Nulls) -> SerializerConfig {
203 self.nulls = nulls;
204 self
205 }
206
207 pub const fn flexible(mut self, yes: bool) -> SerializerConfig {
210 self.flexible = yes;
211 self
212 }
213
214 pub const fn escape_formulas(mut self, yes: bool) -> SerializerConfig {
230 self.escape_formulas = yes;
231 self
232 }
233
234 pub const fn bytes(mut self, format: BytesFormat) -> SerializerConfig {
240 self.bytes = format;
241 self
242 }
243
244 pub fn to_string(&self, value: &dyn Serialize) -> Result<String, Error> {
248 self.to_string_with(value, |_| {})
249 }
250
251 pub fn to_string_with<F>(&self, value: &dyn Serialize, setup: F) -> Result<String, Error>
256 where
257 F: FnOnce(&mut SerializeDriver<'_>),
258 {
259 let mut driver = SerializeDriver::new(value);
260 setup(&mut driver);
261 let mut out = Vec::new();
262 self.write_whole(&mut WriterState::default(), &mut driver, true, &mut out)?;
263 Ok(into_string(out))
264 }
265
266 pub(crate) fn write(
273 &self,
274 state: &mut WriterState,
275 driver: &mut SerializeDriver<'_>,
276 document: bool,
277 out: &mut Vec<u8>,
278 limit: usize,
279 ) -> Result<bool, Error> {
280 let drive: DriveFn = if limit == usize::MAX {
281 drive_whole
282 } else {
283 drive_partial
284 };
285 self.write_with(state, driver, document, out, limit, drive)
286 }
287
288 pub(crate) fn write_whole(
294 &self,
295 state: &mut WriterState,
296 driver: &mut SerializeDriver<'_>,
297 document: bool,
298 out: &mut Vec<u8>,
299 ) -> Result<(), Error> {
300 self.write_with(state, driver, document, out, usize::MAX, drive_whole)
301 .map(|_| ())
302 }
303
304 fn write_with(
306 &self,
307 state: &mut WriterState,
308 driver: &mut SerializeDriver<'_>,
309 document: bool,
310 out: &mut Vec<u8>,
311 limit: usize,
312 drive: DriveFn,
313 ) -> Result<bool, Error> {
314 let dialect = match state.dialect {
315 Some(ref dialect) => dialect,
316 None => state.dialect.insert(Dialect::new(
317 self.delimiter,
318 self.quote,
319 self.double_quote,
320 self.escape,
321 self.terminator,
322 None,
323 )?),
324 };
325 let mut writer = RecordWriter {
326 encoder: FieldEncoder {
327 config: self,
328 dialect,
329 },
330 names: state.names.take(),
331 len: state.len,
332 document,
333 direct: false,
334 is_map: false,
335 fields: 0,
336 record_start: 0,
337 field_ends: core::mem::take(&mut state.buffers.field_ends),
338 record: core::mem::take(&mut state.buffers.record),
339 scratch: core::mem::take(&mut state.buffers.scratch),
340 open: false,
341 limit,
342 out,
343 };
344 let had_names = writer.names.is_some();
345 let rv = drive(driver, &mut writer);
346 if rv.is_ok() || had_names {
349 state.names = writer.names;
350 }
351 if rv.is_ok() {
352 state.len = writer.len;
353 }
354 state.buffers = Buffers {
356 field_ends: writer.field_ends,
357 record: writer.record,
358 scratch: writer.scratch,
359 };
360 rv
361 }
362}
363
364type DriveFn = fn(&mut SerializeDriver<'_>, &mut RecordWriter<'_>) -> Result<bool, Error>;
366
367fn drive_whole(
369 driver: &mut SerializeDriver<'_>,
370 writer: &mut RecordWriter<'_>,
371) -> Result<bool, Error> {
372 driver
373 .drive(|event, state| writer.event(event, state))
374 .map(|()| true)
375}
376
377fn drive_partial(
379 driver: &mut SerializeDriver<'_>,
380 writer: &mut RecordWriter<'_>,
381) -> Result<bool, Error> {
382 driver.drive_until(writer)
383}
384
385#[derive(Clone, Default)]
387struct Buffers {
388 field_ends: Vec<usize>,
389 record: Record,
390 scratch: Vec<u8>,
391}
392
393impl core::fmt::Debug for Buffers {
394 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
395 f.debug_struct("Buffers").finish_non_exhaustive()
396 }
397}
398
399#[derive(Debug, Clone, Default)]
404pub(crate) struct WriterState {
405 names: Option<Vec<String>>,
406 len: Option<usize>,
408 dialect: Option<Dialect>,
410 buffers: Buffers,
411}
412
413impl WriterState {
414 fn with_headers(names: Vec<String>) -> WriterState {
417 WriterState {
418 len: Some(names.len()),
419 names: Some(names),
420 dialect: None,
421 buffers: Buffers::default(),
422 }
423 }
424}
425
426#[derive(Debug, Clone)]
453pub struct Serializer {
454 config: SerializerConfig,
455 state: WriterState,
456 out: Vec<u8>,
457 document: bool,
459 in_progress: bool,
461}
462
463impl Default for Serializer {
464 fn default() -> Serializer {
465 Serializer::new()
466 }
467}
468
469impl Serializer {
470 pub fn new() -> Serializer {
472 Serializer::with_config(&SerializerConfig::new())
473 }
474
475 pub fn with_config(config: &SerializerConfig) -> Serializer {
477 Serializer::with_state(config, WriterState::default(), false)
478 }
479
480 pub fn with_headers<I, S>(config: &SerializerConfig, names: I) -> Serializer
496 where
497 I: IntoIterator<Item = S>,
498 S: Into<String>,
499 {
500 let names = names.into_iter().map(Into::into).collect();
501 Serializer::with_state(config, WriterState::with_headers(names), false)
502 }
503
504 pub fn document(config: &SerializerConfig) -> Serializer {
520 Serializer::with_state(config, WriterState::default(), true)
521 }
522
523 fn with_state(config: &SerializerConfig, state: WriterState, document: bool) -> Serializer {
524 Serializer {
525 config: config.clone(),
526 state,
527 out: Vec::new(),
528 document,
529 in_progress: false,
530 }
531 }
532
533 pub fn config(&self) -> &SerializerConfig {
535 &self.config
536 }
537
538 pub fn headers(&self) -> Option<&[String]> {
543 self.state.names.as_deref()
544 }
545
546 pub fn serialize(&mut self, value: &dyn Serialize) -> Result<(), Error> {
551 ser::Serializer::serialize(self, value)
552 }
553
554 pub fn serialize_with<F>(&mut self, value: &dyn Serialize, setup: F) -> Result<(), Error>
559 where
560 F: FnOnce(&mut SerializeDriver<'_>),
561 {
562 ser::Serializer::serialize_with(self, value, setup)
563 }
564
565 pub fn as_str(&self) -> &str {
567 unsafe { core::str::from_utf8_unchecked(&self.out) }
569 }
570
571 pub fn finish(self) -> String {
573 into_string(self.out)
574 }
575}
576
577impl ser::Serializer for Serializer {
578 fn drive(&mut self, driver: &mut SerializeDriver<'_>) -> Result<(), Error> {
579 if self.in_progress {
580 return Err(Error::in_progress());
581 }
582 let len = self.out.len();
583 match self
584 .config
585 .write_whole(&mut self.state, driver, self.document, &mut self.out)
586 {
587 Ok(()) => Ok(()),
588 Err(err) => {
589 self.out.truncate(len);
590 Err(err)
591 }
592 }
593 }
594}
595
596impl ser::StreamSerializer for Serializer {
597 fn output(&self) -> &[u8] {
598 &self.out
599 }
600
601 fn clear_output(&mut self) {
602 self.out.clear();
603 }
604
605 fn supports_partial(&self) -> bool {
607 self.document
608 }
609
610 fn drive_partial(
611 &mut self,
612 driver: &mut SerializeDriver<'_>,
613 limit: usize,
614 ) -> Result<Written, Error> {
615 if !self.document || (limit == usize::MAX && !self.in_progress) {
616 ser::Serializer::drive(self, driver)?;
617 return Ok(Written::Done);
618 }
619 let len = self.out.len();
620 match self
621 .config
622 .write(&mut self.state, driver, true, &mut self.out, limit)
623 {
624 Ok(true) => {
625 self.in_progress = false;
626 Ok(Written::Done)
627 }
628 Ok(false) => {
629 self.in_progress = true;
630 Ok(Written::Partial)
631 }
632 Err(err) => {
633 self.out.truncate(len);
636 Err(err)
637 }
638 }
639 }
640
641 fn in_progress(&self) -> bool {
642 self.in_progress
643 }
644}
645
646#[cfg(feature = "io")]
647impl SerializerConfig {
648 pub fn writer<W: std::io::Write>(&self, writer: W) -> deser_core::io::Writer<W, Serializer> {
670 deser_core::io::Writer::new(writer, Serializer::with_config(self))
671 }
672
673 pub fn to_writer<W: std::io::Write>(
677 &self,
678 writer: W,
679 value: &dyn Serialize,
680 ) -> Result<(), Error> {
681 deser_core::io::to_writer(writer, Serializer::document(self), value)
682 }
683}
684
685#[cfg(feature = "io")]
698pub fn to_writer<W: std::io::Write>(writer: W, value: &dyn Serialize) -> Result<(), Error> {
699 SerializerConfig::new().to_writer(writer, value)
700}
701
702fn into_string(out: Vec<u8>) -> String {
707 debug_assert!(core::str::from_utf8(&out).is_ok());
708 unsafe { String::from_utf8_unchecked(out) }
710}
711
712pub fn to_string(value: &dyn Serialize) -> Result<String, Error> {
738 SerializerConfig::new().to_string(value)
739}
740
741#[derive(Clone, Default)]
743struct Record {
744 keys: Vec<u8>,
746 key_ends: Vec<usize>,
747 fields: Vec<u8>,
749 field_ends: Vec<usize>,
750}
751
752impl Record {
753 fn clear(&mut self) {
754 self.keys.clear();
755 self.key_ends.clear();
756 self.fields.clear();
757 self.field_ends.clear();
758 }
759
760 fn key(&self, index: usize) -> &[u8] {
761 let start = if index == 0 {
762 0
763 } else {
764 self.key_ends[index - 1]
765 };
766 &self.keys[start..self.key_ends[index]]
767 }
768
769 fn field(&self, index: usize) -> &[u8] {
770 let start = if index == 0 {
771 0
772 } else {
773 self.field_ends[index - 1]
774 };
775 &self.fields[start..self.field_ends[index]]
776 }
777}
778
779struct RecordWriter<'a> {
786 encoder: FieldEncoder<'a>,
787 names: Option<Vec<String>>,
788 len: Option<usize>,
789 document: bool,
790 direct: bool,
792 is_map: bool,
793 fields: usize,
795 record_start: usize,
797 field_ends: Vec<usize>,
800 record: Record,
802 scratch: Vec<u8>,
804 open: bool,
806 limit: usize,
808 out: &'a mut Vec<u8>,
809}
810
811impl PausableSink for RecordWriter<'_> {
812 #[inline]
813 fn event(
814 &mut self,
815 event: Event<'_>,
816 _value: &dyn Serialize,
817 state: &mut State,
818 ) -> Result<(), Error> {
819 RecordWriter::event(self, event, state)
820 }
821
822 #[inline]
823 fn pause(&mut self) -> bool {
824 !self.open && self.out.len() >= self.limit
826 }
827}
828
829impl RecordWriter<'_> {
830 #[inline]
831 fn event(&mut self, event: Event<'_>, state: &State) -> Result<(), Error> {
832 if let Event::Atom(ref atom) = event
834 && state.depth() == usize::from(self.document) + 1
835 {
836 return self.atom(atom, state.is_map_key());
837 }
838 self.structure(event, state)
839 }
840
841 fn structure(&mut self, event: Event<'_>, state: &State) -> Result<(), Error> {
843 let depth = match event {
846 Event::MapStart(_) | Event::SeqStart(_) => state.depth().saturating_sub(1),
847 _ => state.depth(),
848 };
849 let record_depth = usize::from(self.document);
850 match event {
851 Event::SeqStart(_) | Event::SeqEnd if self.document && depth == 0 => {}
852 _ if depth < record_depth => {
853 return Err(Error::new(
854 ErrorKind::UnsupportedType,
855 "CSV documents are sequences of records",
856 ));
857 }
858 Event::MapStart(_) | Event::SeqStart(_) if depth == record_depth => {
859 if self.names.is_none()
860 && let Some(columns) = self.encoder.config.columns
861 {
862 let names: Vec<String> = columns.iter().map(|name| name.to_string()).collect();
863 if self.encoder.config.headers {
864 self.write_names(&names)?;
865 }
866 self.names = Some(names);
867 }
868 self.is_map = matches!(event, Event::MapStart(_));
869 self.open = true;
870 self.direct = !self.is_map || self.names.is_some();
871 self.fields = 0;
872 self.record_start = self.out.len();
873 self.field_ends.clear();
874 self.record.clear();
875 }
876 Event::MapEnd | Event::SeqEnd if depth == record_depth => {
877 self.open = false;
878 self.finish_record()?
879 }
880 _ if depth == record_depth => {
881 return Err(Error::new(
882 ErrorKind::UnsupportedType,
883 "CSV records must be maps or sequences",
884 ));
885 }
886 Event::MapStart(_) | Event::SeqStart(_) | Event::MapEnd | Event::SeqEnd => {
888 return Err(Error::new(
889 ErrorKind::UnsupportedType,
890 "CSV fields cannot hold maps or sequences",
891 ));
892 }
893 Event::Atom(ref atom) => return self.atom(atom, state.is_map_key()),
894 }
895 Ok(())
896 }
897
898 #[inline]
900 fn atom(&mut self, atom: &Atom<'_>, is_key: bool) -> Result<(), Error> {
901 if is_key {
902 return self.key(atom);
903 }
904 let text = self.encoder.text(atom, &mut self.scratch)?;
905 if self.direct {
906 if self.fields > 0 {
907 self.out.push(self.encoder.dialect.delimiter);
908 }
909 self.encoder.encode(text, self.out)?;
910 self.field_ends.push(self.out.len());
911 } else {
912 self.encoder.encode(text, &mut self.record.fields)?;
913 self.record.field_ends.push(self.record.fields.len());
914 }
915 self.fields += 1;
916 Ok(())
917 }
918
919 fn key(&mut self, atom: &Atom<'_>) -> Result<(), Error> {
921 let key = match atom {
922 Atom::Null | Atom::Bytes(_) => None,
923 atom => self.encoder.text(atom, &mut self.scratch)?,
924 };
925 let key = key.ok_or_else(unsupported_key)?;
926 if !self.direct {
927 self.record.keys.extend_from_slice(key.bytes);
928 } else {
929 let names = self.names.as_deref().unwrap_or_default();
930 if names.get(self.fields).map(String::as_bytes) == Some(key.bytes) {
931 return Ok(());
932 }
933 let key = key.bytes.to_vec();
934 self.collect();
935 self.record.keys.extend_from_slice(&key);
936 }
937 self.record.key_ends.push(self.record.keys.len());
938 Ok(())
939 }
940
941 fn collect(&mut self) {
943 let names = self.names.as_deref().unwrap_or_default();
944 let mut start = self.record_start;
945 for (index, &end) in self.field_ends.iter().enumerate() {
946 if index > 0 {
947 start += 1;
949 }
950 self.record.fields.extend_from_slice(&self.out[start..end]);
951 self.record.field_ends.push(self.record.fields.len());
952 self.record.keys.extend_from_slice(names[index].as_bytes());
953 self.record.key_ends.push(self.record.keys.len());
954 start = end;
955 }
956 self.out.truncate(self.record_start);
957 self.direct = false;
958 }
959
960 fn finish_record(&mut self) -> Result<(), Error> {
962 let start = self.record_start;
963 if !self.is_map {
964 self.check_len(self.fields)?;
965 return self.terminate(self.fields, start);
966 }
967
968 if self.direct {
969 let len = self.names.as_ref().map_or(0, Vec::len);
971 for column in self.fields..len {
972 if column > 0 {
973 self.out.push(self.encoder.dialect.delimiter);
974 }
975 self.encoder.encode(None, self.out)?;
976 }
977 self.check_len(len)?;
978 return self.terminate(len, start);
979 }
980
981 let count = self.record.field_ends.len();
982 if self.names.is_none() {
983 let names: Vec<String> = (0..count)
985 .map(|index| String::from_utf8_lossy(self.record.key(index)).into_owned())
986 .collect();
987 if self.encoder.config.headers {
988 self.write_names(&names)?;
989 }
990 self.names = Some(names);
991 }
992 let len = self.names.as_ref().map_or(0, Vec::len);
993 self.check_len(len)?;
994 let names = self.names.as_ref().unwrap();
995 let start = self.out.len();
996 let mut order = vec![None; len];
997 for index in 0..count {
998 let key = String::from_utf8_lossy(self.record.key(index));
999 match names.iter().position(|name| *name == key) {
1000 Some(column) if order[column].is_none() => order[column] = Some(index),
1001 Some(_) => {
1002 return Err(Error::new(
1003 ErrorKind::Unexpected,
1004 format!("duplicate field `{}`", key),
1005 ));
1006 }
1007 None => {
1008 return Err(Error::new(
1009 ErrorKind::Unexpected,
1010 format!("field `{}` is not a column", key),
1011 ));
1012 }
1013 }
1014 }
1015 for (column, index) in order.into_iter().enumerate() {
1016 if column > 0 {
1017 self.out.push(self.encoder.dialect.delimiter);
1018 }
1019 match index {
1020 Some(index) => self.out.extend_from_slice(self.record.field(index)),
1021 None => self.encoder.encode(None, self.out)?,
1023 }
1024 }
1025 self.terminate(len, start)
1026 }
1027
1028 fn check_len(&mut self, len: usize) -> Result<(), Error> {
1030 match self.len {
1031 Some(expected) if expected != len && !self.encoder.config.flexible => Err(Error::new(
1032 ErrorKind::Unexpected,
1033 format!("record has {} fields, expected {}", len, expected),
1034 )),
1035 Some(_) => Ok(()),
1036 None => {
1037 self.len = Some(len);
1038 Ok(())
1039 }
1040 }
1041 }
1042
1043 fn terminate(&mut self, len: usize, start: usize) -> Result<(), Error> {
1046 if len == 1 && self.out.len() == start {
1047 match self.encoder.dialect.quote {
1049 Some(quote) => self.out.extend_from_slice(&[quote, quote]),
1050 None => {
1051 return Err(Error::new(
1052 ErrorKind::Unexpected,
1053 "a record with a single empty field needs quotes",
1054 ));
1055 }
1056 }
1057 }
1058 match self.encoder.config.terminator {
1059 Terminator::Newline => self.out.push(b'\n'),
1060 Terminator::CrLf => self.out.extend_from_slice(b"\r\n"),
1061 Terminator::Byte(byte) => self.out.push(byte),
1062 }
1063 Ok(())
1064 }
1065
1066 fn write_names(&mut self, names: &[String]) -> Result<(), Error> {
1068 let start = self.out.len();
1069 for (index, name) in names.iter().enumerate() {
1070 if index > 0 {
1071 self.out.push(self.encoder.dialect.delimiter);
1072 }
1073 let text = Text {
1074 bytes: name.as_bytes(),
1075 numeric: false,
1076 };
1077 self.encoder.encode(Some(text), self.out)?;
1078 }
1079 self.terminate(names.len(), start)
1080 }
1081}
1082
1083#[derive(Clone, Copy)]
1085struct Text<'a> {
1086 bytes: &'a [u8],
1087 numeric: bool,
1088}
1089
1090#[derive(Clone, Copy)]
1092struct FieldEncoder<'a> {
1093 config: &'a SerializerConfig,
1094 dialect: &'a Dialect,
1095}
1096
1097impl FieldEncoder<'_> {
1098 fn encode(&self, text: Option<Text<'_>>, out: &mut Vec<u8>) -> Result<(), Error> {
1100 let config = self.config;
1101 let Some(Text { bytes, numeric }) = text else {
1102 if let Nulls::Text(null) = config.nulls {
1103 out.extend_from_slice(null.as_bytes());
1104 }
1105 return Ok(());
1106 };
1107 let reads_as_null = match config.nulls {
1108 Nulls::None => false,
1109 Nulls::Empty => bytes.is_empty(),
1110 Nulls::Text(null) => bytes == null.as_bytes(),
1111 };
1112 let formula = config.escape_formulas
1115 && !numeric
1116 && matches!(
1117 bytes.first(),
1118 Some(b'=' | b'+' | b'-' | b'@' | b'\t' | b'\r')
1119 );
1120 let has_special = self.dialect.has_special(bytes);
1121 let quote_style = match config.quote_style {
1122 QuoteStyle::Always => true,
1123 QuoteStyle::NonNumeric => !numeric,
1124 QuoteStyle::Necessary | QuoteStyle::Never => false,
1125 };
1126 if !quote_style && !has_special && !reads_as_null && !formula {
1127 out.extend_from_slice(bytes);
1128 return Ok(());
1129 }
1130
1131 let prefix: &[u8] = if formula { b"'" } else { b"" };
1132 let escape = config.escape.byte();
1133 let prefix_is_special = formula && self.dialect.is_special(b'\'');
1134 let quoted = quote_style
1137 || (formula && self.dialect.quote.is_some() && config.quote_style != QuoteStyle::Never)
1138 || (escape.is_none() && (has_special || prefix_is_special || reads_as_null))
1139 || (reads_as_null && bytes.is_empty());
1140 let text = prefix.iter().chain(bytes).copied();
1141
1142 if !quoted {
1143 for (index, byte) in text.enumerate() {
1144 if self.dialect.is_special(byte) || (index == 0 && reads_as_null) {
1145 out.push(escape.unwrap_or(b'\\'));
1147 out.push(self.escaped(byte));
1148 } else {
1149 out.push(byte);
1150 }
1151 }
1152 return Ok(());
1153 }
1154
1155 let quote = match self.dialect.quote {
1156 Some(quote) if config.quote_style != QuoteStyle::Never => quote,
1157 _ => {
1158 return Err(Error::new(
1159 ErrorKind::Unexpected,
1160 format!(
1161 "field {:?} needs to be quoted",
1162 String::from_utf8_lossy(bytes)
1163 ),
1164 ));
1165 }
1166 };
1167 out.push(quote);
1168 if formula {
1169 self.push_quoted(b'\'', quote, out)?;
1170 }
1171 let mut bytes = bytes;
1172 loop {
1173 let run = bytes
1175 .iter()
1176 .position(|&b| b == quote || Some(b) == escape)
1177 .unwrap_or(bytes.len());
1178 out.extend_from_slice(&bytes[..run]);
1179 let Some((&byte, rest)) = bytes[run..].split_first() else {
1180 break;
1181 };
1182 bytes = rest;
1183 self.push_quoted(byte, quote, out)?;
1184 }
1185 out.push(quote);
1186 Ok(())
1187 }
1188
1189 fn push_quoted(&self, byte: u8, quote: u8, out: &mut Vec<u8>) -> Result<(), Error> {
1191 let escape = self.config.escape.byte();
1192 if byte == quote && self.config.double_quote {
1193 out.extend_from_slice(&[quote, quote]);
1194 } else if byte == quote || Some(byte) == escape {
1195 match escape {
1196 Some(escape) => out.extend_from_slice(&[escape, self.escaped(byte)]),
1197 None => {
1198 return Err(Error::new(
1199 ErrorKind::Unexpected,
1200 "quotes in quoted fields need to be doubled or escaped",
1201 ));
1202 }
1203 }
1204 } else {
1205 out.push(byte);
1206 }
1207 Ok(())
1208 }
1209
1210 fn escaped(&self, byte: u8) -> u8 {
1212 match (self.config.escape, byte) {
1213 (Escape::Backslash, b'\t') => b't',
1214 (Escape::Backslash, b'\n') => b'n',
1215 (Escape::Backslash, b'\r') => b'r',
1216 (_, byte) => byte,
1217 }
1218 }
1219
1220 fn text<'a>(
1224 &self,
1225 atom: &'a Atom<'_>,
1226 scratch: &'a mut Vec<u8>,
1227 ) -> Result<Option<Text<'a>>, Error> {
1228 scratch.clear();
1229 let numeric = match *atom {
1230 Atom::Null => return Ok(None),
1231 Atom::Bool(value) => {
1232 let text: &[u8] = if value { b"true" } else { b"false" };
1233 return Ok(Some(Text {
1234 bytes: text,
1235 numeric: false,
1236 }));
1237 }
1238 Atom::Str(ref value) | Atom::Lexical(ref value) => {
1239 return Ok(Some(Text {
1240 bytes: value.as_bytes(),
1241 numeric: false,
1242 }));
1243 }
1244 Atom::Char(value) => {
1245 scratch.extend_from_slice(value.encode_utf8(&mut [0; 4]).as_bytes());
1246 false
1247 }
1248 Atom::U64(value) => {
1249 scratch.extend_from_slice(IntBuffer::new().format_u64(value).as_bytes());
1250 true
1251 }
1252 Atom::I64(value) => {
1253 scratch.extend_from_slice(IntBuffer::new().format_i64(value).as_bytes());
1254 true
1255 }
1256 Atom::F32(value) => {
1257 write_float(scratch, value);
1258 true
1259 }
1260 Atom::F64(value) => {
1261 write_float(scratch, value);
1262 true
1263 }
1264 Atom::Bytes(ref bytes) => {
1265 let format = bytes.fallback.copied().unwrap_or(self.config.bytes);
1266 let text = format
1267 .encode(bytes)
1268 .or_else(|| BytesFormat::BASE64.encode(bytes))
1269 .unwrap_or_default();
1270 scratch.extend_from_slice(text.as_bytes());
1271 false
1272 }
1273 Atom::Ext(ref ext) => {
1274 if let Some(number) = ext.downcast_value_ref::<Number>() {
1275 scratch.extend_from_slice(number.as_str().as_bytes());
1277 } else if let Some(value) = ext.downcast_ref::<u128>() {
1278 let _ = write!(ByteWriter(scratch), "{}", value);
1279 } else if let Some(value) = ext.downcast_ref::<i128>() {
1280 let _ = write!(ByteWriter(scratch), "{}", value);
1281 } else {
1282 return match ext.fallback() {
1283 Atom::Ext(_) => Err(Error::new(
1284 ErrorKind::UnsupportedType,
1285 format!("CSV does not support {}", ext.name()),
1286 )),
1287 fallback => {
1288 let mut inner = Vec::new();
1289 let numeric = match self.text(&fallback, &mut inner)? {
1290 Some(text) => {
1291 let numeric = text.numeric;
1292 scratch.extend_from_slice(text.bytes);
1293 numeric
1294 }
1295 None => return Ok(None),
1296 };
1297 Ok(Some(Text {
1298 bytes: scratch,
1299 numeric,
1300 }))
1301 }
1302 };
1303 }
1304 true
1305 }
1306 Atom::Implicit(ref value) => {
1308 let mut inner = Vec::new();
1309 return Ok(match self.text(&value.value().to_atom(), &mut inner)? {
1310 Some(text) => {
1311 let numeric = text.numeric;
1312 scratch.extend_from_slice(text.bytes);
1313 Some(Text {
1314 bytes: scratch,
1315 numeric,
1316 })
1317 }
1318 None => None,
1319 });
1320 }
1321 _ => {
1322 return Err(Error::new(
1323 ErrorKind::UnsupportedType,
1324 format!("CSV does not support {}", atom.name()),
1325 ));
1326 }
1327 };
1328 Ok(Some(Text {
1329 bytes: scratch,
1330 numeric,
1331 }))
1332 }
1333}
1334
1335struct ByteWriter<'a>(&'a mut Vec<u8>);
1337
1338impl fmt::Write for ByteWriter<'_> {
1339 fn write_str(&mut self, s: &str) -> fmt::Result {
1340 self.0.extend_from_slice(s.as_bytes());
1341 Ok(())
1342 }
1343}
1344
1345fn write_float<F: Float>(out: &mut Vec<u8>, value: F) {
1348 if value.is_finite() {
1349 out.extend_from_slice(format_finite(value).as_bytes());
1350 } else {
1351 let _ = write!(ByteWriter(out), "{}", value.to_f64());
1353 }
1354}
1355
1356#[cold]
1357fn unsupported_key() -> Error {
1358 Error::new(
1359 ErrorKind::UnsupportedType,
1360 "the keys of records must be strings, numbers or booleans",
1361 )
1362}