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(
263 &mut WriterState::default(),
264 &mut driver,
265 true,
266 &mut out,
267 usize::MAX,
268 )?;
269 Ok(into_string(out))
270 }
271
272 pub(crate) fn write(
279 &self,
280 state: &mut WriterState,
281 driver: &mut SerializeDriver<'_>,
282 document: bool,
283 out: &mut Vec<u8>,
284 limit: usize,
285 ) -> Result<bool, Error> {
286 let dialect = match state.dialect {
287 Some(ref dialect) => dialect,
288 None => state.dialect.insert(Dialect::new(
289 self.delimiter,
290 self.quote,
291 self.double_quote,
292 self.escape,
293 self.terminator,
294 None,
295 )?),
296 };
297 let mut writer = RecordWriter {
298 encoder: FieldEncoder {
299 config: self,
300 dialect,
301 },
302 names: state.names.take(),
303 len: state.len,
304 document,
305 direct: false,
306 is_map: false,
307 fields: 0,
308 record_start: 0,
309 field_ends: core::mem::take(&mut state.buffers.field_ends),
310 record: core::mem::take(&mut state.buffers.record),
311 scratch: core::mem::take(&mut state.buffers.scratch),
312 open: false,
313 limit,
314 out,
315 };
316 let had_names = writer.names.is_some();
317 let rv = if limit == usize::MAX {
318 driver
319 .drive(|event, state| writer.event(event, state))
320 .map(|()| true)
321 } else {
322 driver.drive_until(&mut writer)
323 };
324 if rv.is_ok() || had_names {
327 state.names = writer.names;
328 }
329 if rv.is_ok() {
330 state.len = writer.len;
331 }
332 state.buffers = Buffers {
334 field_ends: writer.field_ends,
335 record: writer.record,
336 scratch: writer.scratch,
337 };
338 rv
339 }
340}
341
342#[derive(Clone, Default)]
344struct Buffers {
345 field_ends: Vec<usize>,
346 record: Record,
347 scratch: Vec<u8>,
348}
349
350impl core::fmt::Debug for Buffers {
351 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
352 f.debug_struct("Buffers").finish_non_exhaustive()
353 }
354}
355
356#[derive(Debug, Clone, Default)]
361pub(crate) struct WriterState {
362 names: Option<Vec<String>>,
363 len: Option<usize>,
365 dialect: Option<Dialect>,
367 buffers: Buffers,
368}
369
370impl WriterState {
371 fn with_headers(names: Vec<String>) -> WriterState {
374 WriterState {
375 len: Some(names.len()),
376 names: Some(names),
377 dialect: None,
378 buffers: Buffers::default(),
379 }
380 }
381}
382
383#[derive(Debug, Clone)]
410pub struct Serializer {
411 config: SerializerConfig,
412 state: WriterState,
413 out: Vec<u8>,
414 document: bool,
416 in_progress: bool,
418}
419
420impl Default for Serializer {
421 fn default() -> Serializer {
422 Serializer::new()
423 }
424}
425
426impl Serializer {
427 pub fn new() -> Serializer {
429 Serializer::with_config(&SerializerConfig::new())
430 }
431
432 pub fn with_config(config: &SerializerConfig) -> Serializer {
434 Serializer::with_state(config, WriterState::default(), false)
435 }
436
437 pub fn with_headers<I, S>(config: &SerializerConfig, names: I) -> Serializer
453 where
454 I: IntoIterator<Item = S>,
455 S: Into<String>,
456 {
457 let names = names.into_iter().map(Into::into).collect();
458 Serializer::with_state(config, WriterState::with_headers(names), false)
459 }
460
461 pub fn document(config: &SerializerConfig) -> Serializer {
477 Serializer::with_state(config, WriterState::default(), true)
478 }
479
480 fn with_state(config: &SerializerConfig, state: WriterState, document: bool) -> Serializer {
481 Serializer {
482 config: config.clone(),
483 state,
484 out: Vec::new(),
485 document,
486 in_progress: false,
487 }
488 }
489
490 pub fn config(&self) -> &SerializerConfig {
492 &self.config
493 }
494
495 pub fn headers(&self) -> Option<&[String]> {
500 self.state.names.as_deref()
501 }
502
503 pub fn serialize(&mut self, value: &dyn Serialize) -> Result<(), Error> {
508 ser::Serializer::serialize(self, value)
509 }
510
511 pub fn serialize_with<F>(&mut self, value: &dyn Serialize, setup: F) -> Result<(), Error>
516 where
517 F: FnOnce(&mut SerializeDriver<'_>),
518 {
519 ser::Serializer::serialize_with(self, value, setup)
520 }
521
522 pub fn as_str(&self) -> &str {
524 unsafe { core::str::from_utf8_unchecked(&self.out) }
526 }
527
528 pub fn finish(self) -> String {
530 into_string(self.out)
531 }
532}
533
534impl ser::Serializer for Serializer {
535 fn drive(&mut self, driver: &mut SerializeDriver<'_>) -> Result<(), Error> {
536 if self.in_progress {
537 return Err(Error::in_progress());
538 }
539 let len = self.out.len();
540 match self.config.write(
541 &mut self.state,
542 driver,
543 self.document,
544 &mut self.out,
545 usize::MAX,
546 ) {
547 Ok(_) => Ok(()),
548 Err(err) => {
549 self.out.truncate(len);
550 Err(err)
551 }
552 }
553 }
554}
555
556impl ser::StreamSerializer for Serializer {
557 fn output(&self) -> &[u8] {
558 &self.out
559 }
560
561 fn clear_output(&mut self) {
562 self.out.clear();
563 }
564
565 fn supports_partial(&self) -> bool {
567 self.document
568 }
569
570 fn drive_partial(
571 &mut self,
572 driver: &mut SerializeDriver<'_>,
573 limit: usize,
574 ) -> Result<Written, Error> {
575 if !self.document || (limit == usize::MAX && !self.in_progress) {
576 ser::Serializer::drive(self, driver)?;
577 return Ok(Written::Done);
578 }
579 let len = self.out.len();
580 match self
581 .config
582 .write(&mut self.state, driver, true, &mut self.out, limit)
583 {
584 Ok(true) => {
585 self.in_progress = false;
586 Ok(Written::Done)
587 }
588 Ok(false) => {
589 self.in_progress = true;
590 Ok(Written::Partial)
591 }
592 Err(err) => {
593 self.out.truncate(len);
596 Err(err)
597 }
598 }
599 }
600
601 fn in_progress(&self) -> bool {
602 self.in_progress
603 }
604}
605
606#[cfg(feature = "io")]
607impl SerializerConfig {
608 pub fn writer<W: std::io::Write>(&self, writer: W) -> deser_core::io::Writer<W, Serializer> {
630 deser_core::io::Writer::new(writer, Serializer::with_config(self))
631 }
632
633 pub fn to_writer<W: std::io::Write>(
637 &self,
638 writer: W,
639 value: &dyn Serialize,
640 ) -> Result<(), Error> {
641 deser_core::io::to_writer(writer, Serializer::document(self), value)
642 }
643}
644
645#[cfg(feature = "io")]
658pub fn to_writer<W: std::io::Write>(writer: W, value: &dyn Serialize) -> Result<(), Error> {
659 SerializerConfig::new().to_writer(writer, value)
660}
661
662fn into_string(out: Vec<u8>) -> String {
667 debug_assert!(core::str::from_utf8(&out).is_ok());
668 unsafe { String::from_utf8_unchecked(out) }
670}
671
672pub fn to_string(value: &dyn Serialize) -> Result<String, Error> {
698 SerializerConfig::new().to_string(value)
699}
700
701#[derive(Clone, Default)]
703struct Record {
704 keys: Vec<u8>,
706 key_ends: Vec<usize>,
707 fields: Vec<u8>,
709 field_ends: Vec<usize>,
710}
711
712impl Record {
713 fn clear(&mut self) {
714 self.keys.clear();
715 self.key_ends.clear();
716 self.fields.clear();
717 self.field_ends.clear();
718 }
719
720 fn key(&self, index: usize) -> &[u8] {
721 let start = if index == 0 {
722 0
723 } else {
724 self.key_ends[index - 1]
725 };
726 &self.keys[start..self.key_ends[index]]
727 }
728
729 fn field(&self, index: usize) -> &[u8] {
730 let start = if index == 0 {
731 0
732 } else {
733 self.field_ends[index - 1]
734 };
735 &self.fields[start..self.field_ends[index]]
736 }
737}
738
739struct RecordWriter<'a> {
746 encoder: FieldEncoder<'a>,
747 names: Option<Vec<String>>,
748 len: Option<usize>,
749 document: bool,
750 direct: bool,
752 is_map: bool,
753 fields: usize,
755 record_start: usize,
757 field_ends: Vec<usize>,
760 record: Record,
762 scratch: Vec<u8>,
764 open: bool,
766 limit: usize,
768 out: &'a mut Vec<u8>,
769}
770
771impl PausableSink for RecordWriter<'_> {
772 #[inline]
773 fn event(
774 &mut self,
775 event: Event<'_>,
776 _value: &dyn Serialize,
777 state: &mut State,
778 ) -> Result<(), Error> {
779 RecordWriter::event(self, event, state)
780 }
781
782 #[inline]
783 fn pause(&mut self) -> bool {
784 !self.open && self.out.len() >= self.limit
786 }
787}
788
789impl RecordWriter<'_> {
790 #[inline]
791 fn event(&mut self, event: Event<'_>, state: &State) -> Result<(), Error> {
792 if let Event::Atom(ref atom) = event
794 && state.depth() == usize::from(self.document) + 1
795 {
796 return self.atom(atom, state.is_map_key());
797 }
798 self.structure(event, state)
799 }
800
801 fn structure(&mut self, event: Event<'_>, state: &State) -> Result<(), Error> {
803 let depth = match event {
806 Event::MapStart(_) | Event::SeqStart(_) => state.depth().saturating_sub(1),
807 _ => state.depth(),
808 };
809 let record_depth = usize::from(self.document);
810 match event {
811 Event::SeqStart(_) | Event::SeqEnd if self.document && depth == 0 => {}
812 _ if depth < record_depth => {
813 return Err(Error::new(
814 ErrorKind::UnsupportedType,
815 "CSV documents are sequences of records",
816 ));
817 }
818 Event::MapStart(_) | Event::SeqStart(_) if depth == record_depth => {
819 if self.names.is_none()
820 && let Some(columns) = self.encoder.config.columns
821 {
822 let names: Vec<String> = columns.iter().map(|name| name.to_string()).collect();
823 if self.encoder.config.headers {
824 self.write_names(&names)?;
825 }
826 self.names = Some(names);
827 }
828 self.is_map = matches!(event, Event::MapStart(_));
829 self.open = true;
830 self.direct = !self.is_map || self.names.is_some();
831 self.fields = 0;
832 self.record_start = self.out.len();
833 self.field_ends.clear();
834 self.record.clear();
835 }
836 Event::MapEnd | Event::SeqEnd if depth == record_depth => {
837 self.open = false;
838 self.finish_record()?
839 }
840 _ if depth == record_depth => {
841 return Err(Error::new(
842 ErrorKind::UnsupportedType,
843 "CSV records must be maps or sequences",
844 ));
845 }
846 Event::MapStart(_) | Event::SeqStart(_) | Event::MapEnd | Event::SeqEnd => {
848 return Err(Error::new(
849 ErrorKind::UnsupportedType,
850 "CSV fields cannot hold maps or sequences",
851 ));
852 }
853 Event::Atom(ref atom) => return self.atom(atom, state.is_map_key()),
854 }
855 Ok(())
856 }
857
858 #[inline]
860 fn atom(&mut self, atom: &Atom<'_>, is_key: bool) -> Result<(), Error> {
861 if is_key {
862 return self.key(atom);
863 }
864 let text = self.encoder.text(atom, &mut self.scratch)?;
865 if self.direct {
866 if self.fields > 0 {
867 self.out.push(self.encoder.dialect.delimiter);
868 }
869 self.encoder.encode(text, self.out)?;
870 self.field_ends.push(self.out.len());
871 } else {
872 self.encoder.encode(text, &mut self.record.fields)?;
873 self.record.field_ends.push(self.record.fields.len());
874 }
875 self.fields += 1;
876 Ok(())
877 }
878
879 fn key(&mut self, atom: &Atom<'_>) -> Result<(), Error> {
881 let key = match atom {
882 Atom::Null | Atom::Bytes(_) => None,
883 atom => self.encoder.text(atom, &mut self.scratch)?,
884 };
885 let key = key.ok_or_else(unsupported_key)?;
886 if !self.direct {
887 self.record.keys.extend_from_slice(key.bytes);
888 } else {
889 let names = self.names.as_deref().unwrap_or_default();
890 if names.get(self.fields).map(String::as_bytes) == Some(key.bytes) {
891 return Ok(());
892 }
893 let key = key.bytes.to_vec();
894 self.collect();
895 self.record.keys.extend_from_slice(&key);
896 }
897 self.record.key_ends.push(self.record.keys.len());
898 Ok(())
899 }
900
901 fn collect(&mut self) {
903 let names = self.names.as_deref().unwrap_or_default();
904 let mut start = self.record_start;
905 for (index, &end) in self.field_ends.iter().enumerate() {
906 if index > 0 {
907 start += 1;
909 }
910 self.record.fields.extend_from_slice(&self.out[start..end]);
911 self.record.field_ends.push(self.record.fields.len());
912 self.record.keys.extend_from_slice(names[index].as_bytes());
913 self.record.key_ends.push(self.record.keys.len());
914 start = end;
915 }
916 self.out.truncate(self.record_start);
917 self.direct = false;
918 }
919
920 fn finish_record(&mut self) -> Result<(), Error> {
922 let start = self.record_start;
923 if !self.is_map {
924 self.check_len(self.fields)?;
925 return self.terminate(self.fields, start);
926 }
927
928 if self.direct {
929 let len = self.names.as_ref().map_or(0, Vec::len);
931 for column in self.fields..len {
932 if column > 0 {
933 self.out.push(self.encoder.dialect.delimiter);
934 }
935 self.encoder.encode(None, self.out)?;
936 }
937 self.check_len(len)?;
938 return self.terminate(len, start);
939 }
940
941 let count = self.record.field_ends.len();
942 if self.names.is_none() {
943 let names: Vec<String> = (0..count)
945 .map(|index| String::from_utf8_lossy(self.record.key(index)).into_owned())
946 .collect();
947 if self.encoder.config.headers {
948 self.write_names(&names)?;
949 }
950 self.names = Some(names);
951 }
952 let len = self.names.as_ref().map_or(0, Vec::len);
953 self.check_len(len)?;
954 let names = self.names.as_ref().unwrap();
955 let start = self.out.len();
956 let mut order = vec![None; len];
957 for index in 0..count {
958 let key = String::from_utf8_lossy(self.record.key(index));
959 match names.iter().position(|name| *name == key) {
960 Some(column) if order[column].is_none() => order[column] = Some(index),
961 Some(_) => {
962 return Err(Error::new(
963 ErrorKind::Unexpected,
964 format!("duplicate field `{}`", key),
965 ));
966 }
967 None => {
968 return Err(Error::new(
969 ErrorKind::Unexpected,
970 format!("field `{}` is not a column", key),
971 ));
972 }
973 }
974 }
975 for (column, index) in order.into_iter().enumerate() {
976 if column > 0 {
977 self.out.push(self.encoder.dialect.delimiter);
978 }
979 match index {
980 Some(index) => self.out.extend_from_slice(self.record.field(index)),
981 None => self.encoder.encode(None, self.out)?,
983 }
984 }
985 self.terminate(len, start)
986 }
987
988 fn check_len(&mut self, len: usize) -> Result<(), Error> {
990 match self.len {
991 Some(expected) if expected != len && !self.encoder.config.flexible => Err(Error::new(
992 ErrorKind::Unexpected,
993 format!("record has {} fields, expected {}", len, expected),
994 )),
995 Some(_) => Ok(()),
996 None => {
997 self.len = Some(len);
998 Ok(())
999 }
1000 }
1001 }
1002
1003 fn terminate(&mut self, len: usize, start: usize) -> Result<(), Error> {
1006 if len == 1 && self.out.len() == start {
1007 match self.encoder.dialect.quote {
1009 Some(quote) => self.out.extend_from_slice(&[quote, quote]),
1010 None => {
1011 return Err(Error::new(
1012 ErrorKind::Unexpected,
1013 "a record with a single empty field needs quotes",
1014 ));
1015 }
1016 }
1017 }
1018 match self.encoder.config.terminator {
1019 Terminator::Newline => self.out.push(b'\n'),
1020 Terminator::CrLf => self.out.extend_from_slice(b"\r\n"),
1021 Terminator::Byte(byte) => self.out.push(byte),
1022 }
1023 Ok(())
1024 }
1025
1026 fn write_names(&mut self, names: &[String]) -> Result<(), Error> {
1028 let start = self.out.len();
1029 for (index, name) in names.iter().enumerate() {
1030 if index > 0 {
1031 self.out.push(self.encoder.dialect.delimiter);
1032 }
1033 let text = Text {
1034 bytes: name.as_bytes(),
1035 numeric: false,
1036 };
1037 self.encoder.encode(Some(text), self.out)?;
1038 }
1039 self.terminate(names.len(), start)
1040 }
1041}
1042
1043#[derive(Clone, Copy)]
1045struct Text<'a> {
1046 bytes: &'a [u8],
1047 numeric: bool,
1048}
1049
1050#[derive(Clone, Copy)]
1052struct FieldEncoder<'a> {
1053 config: &'a SerializerConfig,
1054 dialect: &'a Dialect,
1055}
1056
1057impl FieldEncoder<'_> {
1058 fn encode(&self, text: Option<Text<'_>>, out: &mut Vec<u8>) -> Result<(), Error> {
1060 let config = self.config;
1061 let Some(Text { bytes, numeric }) = text else {
1062 if let Nulls::Text(null) = config.nulls {
1063 out.extend_from_slice(null.as_bytes());
1064 }
1065 return Ok(());
1066 };
1067 let reads_as_null = match config.nulls {
1068 Nulls::None => false,
1069 Nulls::Empty => bytes.is_empty(),
1070 Nulls::Text(null) => bytes == null.as_bytes(),
1071 };
1072 let formula = config.escape_formulas
1075 && !numeric
1076 && matches!(
1077 bytes.first(),
1078 Some(b'=' | b'+' | b'-' | b'@' | b'\t' | b'\r')
1079 );
1080 let has_special = self.dialect.has_special(bytes);
1081 let quote_style = match config.quote_style {
1082 QuoteStyle::Always => true,
1083 QuoteStyle::NonNumeric => !numeric,
1084 QuoteStyle::Necessary | QuoteStyle::Never => false,
1085 };
1086 if !quote_style && !has_special && !reads_as_null && !formula {
1087 out.extend_from_slice(bytes);
1088 return Ok(());
1089 }
1090
1091 let prefix: &[u8] = if formula { b"'" } else { b"" };
1092 let escape = config.escape.byte();
1093 let prefix_is_special = formula && self.dialect.is_special(b'\'');
1094 let quoted = quote_style
1097 || (formula && self.dialect.quote.is_some() && config.quote_style != QuoteStyle::Never)
1098 || (escape.is_none() && (has_special || prefix_is_special || reads_as_null))
1099 || (reads_as_null && bytes.is_empty());
1100 let text = prefix.iter().chain(bytes).copied();
1101
1102 if !quoted {
1103 for (index, byte) in text.enumerate() {
1104 if self.dialect.is_special(byte) || (index == 0 && reads_as_null) {
1105 out.push(escape.unwrap_or(b'\\'));
1107 out.push(self.escaped(byte));
1108 } else {
1109 out.push(byte);
1110 }
1111 }
1112 return Ok(());
1113 }
1114
1115 let quote = match self.dialect.quote {
1116 Some(quote) if config.quote_style != QuoteStyle::Never => quote,
1117 _ => {
1118 return Err(Error::new(
1119 ErrorKind::Unexpected,
1120 format!(
1121 "field {:?} needs to be quoted",
1122 String::from_utf8_lossy(bytes)
1123 ),
1124 ));
1125 }
1126 };
1127 out.push(quote);
1128 if formula {
1129 self.push_quoted(b'\'', quote, out)?;
1130 }
1131 let mut bytes = bytes;
1132 loop {
1133 let run = bytes
1135 .iter()
1136 .position(|&b| b == quote || Some(b) == escape)
1137 .unwrap_or(bytes.len());
1138 out.extend_from_slice(&bytes[..run]);
1139 let Some((&byte, rest)) = bytes[run..].split_first() else {
1140 break;
1141 };
1142 bytes = rest;
1143 self.push_quoted(byte, quote, out)?;
1144 }
1145 out.push(quote);
1146 Ok(())
1147 }
1148
1149 fn push_quoted(&self, byte: u8, quote: u8, out: &mut Vec<u8>) -> Result<(), Error> {
1151 let escape = self.config.escape.byte();
1152 if byte == quote && self.config.double_quote {
1153 out.extend_from_slice(&[quote, quote]);
1154 } else if byte == quote || Some(byte) == escape {
1155 match escape {
1156 Some(escape) => out.extend_from_slice(&[escape, self.escaped(byte)]),
1157 None => {
1158 return Err(Error::new(
1159 ErrorKind::Unexpected,
1160 "quotes in quoted fields need to be doubled or escaped",
1161 ));
1162 }
1163 }
1164 } else {
1165 out.push(byte);
1166 }
1167 Ok(())
1168 }
1169
1170 fn escaped(&self, byte: u8) -> u8 {
1172 match (self.config.escape, byte) {
1173 (Escape::Backslash, b'\t') => b't',
1174 (Escape::Backslash, b'\n') => b'n',
1175 (Escape::Backslash, b'\r') => b'r',
1176 (_, byte) => byte,
1177 }
1178 }
1179
1180 fn text<'a>(
1184 &self,
1185 atom: &'a Atom<'_>,
1186 scratch: &'a mut Vec<u8>,
1187 ) -> Result<Option<Text<'a>>, Error> {
1188 scratch.clear();
1189 let numeric = match *atom {
1190 Atom::Null => return Ok(None),
1191 Atom::Bool(value) => {
1192 let text: &[u8] = if value { b"true" } else { b"false" };
1193 return Ok(Some(Text {
1194 bytes: text,
1195 numeric: false,
1196 }));
1197 }
1198 Atom::Str(ref value) | Atom::Lexical(ref value) => {
1199 return Ok(Some(Text {
1200 bytes: value.as_bytes(),
1201 numeric: false,
1202 }));
1203 }
1204 Atom::Char(value) => {
1205 scratch.extend_from_slice(value.encode_utf8(&mut [0; 4]).as_bytes());
1206 false
1207 }
1208 Atom::U64(value) => {
1209 scratch.extend_from_slice(IntBuffer::new().format_u64(value).as_bytes());
1210 true
1211 }
1212 Atom::I64(value) => {
1213 scratch.extend_from_slice(IntBuffer::new().format_i64(value).as_bytes());
1214 true
1215 }
1216 Atom::F32(value) => {
1217 write_float(scratch, value);
1218 true
1219 }
1220 Atom::F64(value) => {
1221 write_float(scratch, value);
1222 true
1223 }
1224 Atom::Bytes(ref bytes) => {
1225 let format = bytes.fallback.copied().unwrap_or(self.config.bytes);
1226 let text = format
1227 .encode(bytes)
1228 .or_else(|| BytesFormat::BASE64.encode(bytes))
1229 .unwrap_or_default();
1230 scratch.extend_from_slice(text.as_bytes());
1231 false
1232 }
1233 Atom::Ext(ref ext) => {
1234 if let Some(number) = ext.downcast_value_ref::<Number>() {
1235 scratch.extend_from_slice(number.as_str().as_bytes());
1237 } else if let Some(value) = ext.downcast_ref::<u128>() {
1238 let _ = write!(ByteWriter(scratch), "{}", value);
1239 } else if let Some(value) = ext.downcast_ref::<i128>() {
1240 let _ = write!(ByteWriter(scratch), "{}", value);
1241 } else {
1242 return match ext.fallback() {
1243 Atom::Ext(_) => Err(Error::new(
1244 ErrorKind::UnsupportedType,
1245 format!("CSV does not support {}", ext.name()),
1246 )),
1247 fallback => {
1248 let mut inner = Vec::new();
1249 let numeric = match self.text(&fallback, &mut inner)? {
1250 Some(text) => {
1251 let numeric = text.numeric;
1252 scratch.extend_from_slice(text.bytes);
1253 numeric
1254 }
1255 None => return Ok(None),
1256 };
1257 Ok(Some(Text {
1258 bytes: scratch,
1259 numeric,
1260 }))
1261 }
1262 };
1263 }
1264 true
1265 }
1266 Atom::Implicit(ref value) => {
1268 let mut inner = Vec::new();
1269 return Ok(match self.text(&value.value().to_atom(), &mut inner)? {
1270 Some(text) => {
1271 let numeric = text.numeric;
1272 scratch.extend_from_slice(text.bytes);
1273 Some(Text {
1274 bytes: scratch,
1275 numeric,
1276 })
1277 }
1278 None => None,
1279 });
1280 }
1281 _ => {
1282 return Err(Error::new(
1283 ErrorKind::UnsupportedType,
1284 format!("CSV does not support {}", atom.name()),
1285 ));
1286 }
1287 };
1288 Ok(Some(Text {
1289 bytes: scratch,
1290 numeric,
1291 }))
1292 }
1293}
1294
1295struct ByteWriter<'a>(&'a mut Vec<u8>);
1297
1298impl fmt::Write for ByteWriter<'_> {
1299 fn write_str(&mut self, s: &str) -> fmt::Result {
1300 self.0.extend_from_slice(s.as_bytes());
1301 Ok(())
1302 }
1303}
1304
1305fn write_float<F: Float>(out: &mut Vec<u8>, value: F) {
1308 if value.is_finite() {
1309 out.extend_from_slice(format_finite(value).as_bytes());
1310 } else {
1311 let _ = write!(ByteWriter(out), "{}", value.to_f64());
1313 }
1314}
1315
1316#[cold]
1317fn unsupported_key() -> Error {
1318 Error::new(
1319 ErrorKind::UnsupportedType,
1320 "the keys of records must be strings, numbers or booleans",
1321 )
1322}