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::ext::Number;
9use deser_core::ser::SerializeRef;
10use deser_core::ser::{self, EventSink, SerializeDriver};
11use deser_core::{Atom, BytesFormat, Error, ErrorKind, Event, Serialize, State};
12
13use crate::parser::{Dialect, load_u32, load_u64};
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 context: deser_core::Context,
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 context: deser_core::Context::new(),
88 }
89 }
90
91 pub const fn builder() -> SerializerConfigBuilder {
93 SerializerConfigBuilder::new()
94 }
95
96 pub const fn into_builder(self) -> SerializerConfigBuilder {
98 SerializerConfigBuilder { value: self }
99 }
100
101 pub fn set_context(&mut self, context: deser_core::Context) {
109 self.context = context;
110 }
111
112 pub fn context(&self) -> &deser_core::Context {
114 &self.context
115 }
116
117 #[inline]
119 fn apply_context(&self, driver: &mut SerializeDriver<'_>) {
120 if !self.context.is_empty() {
121 driver.set_default_context(self.context.clone());
122 }
123 }
124
125 pub const fn tsv() -> SerializerConfig {
138 let mut config = SerializerConfig::new();
139 config.set_delimiter(b'\t');
140 config.set_quote(None);
141 config.set_escape(Escape::Backslash);
142 config.set_nulls(Nulls::Text("\\N"));
143 config
144 }
145
146 pub const fn set_delimiter(&mut self, delimiter: u8) {
148 self.delimiter = delimiter;
149 }
150
151 pub const fn set_quote(&mut self, quote: Option<u8>) {
156 self.quote = quote;
157 }
158
159 pub const fn set_double_quote(&mut self, yes: bool) {
163 self.double_quote = yes;
164 }
165
166 pub const fn set_escape(&mut self, escape: Escape) {
171 self.escape = escape;
172 }
173
174 pub const fn set_terminator(&mut self, terminator: Terminator) {
176 self.terminator = terminator;
177 }
178
179 pub const fn set_quote_style(&mut self, style: QuoteStyle) {
181 self.quote_style = style;
182 }
183
184 pub const fn set_headers(&mut self, yes: bool) {
191 self.headers = yes;
192 }
193
194 pub const fn set_columns(&mut self, names: &'static [&'static str]) {
221 self.columns = Some(names);
222 }
223
224 pub const fn set_nulls(&mut self, nulls: Nulls) {
230 self.nulls = nulls;
231 }
232
233 pub const fn set_flexible(&mut self, yes: bool) {
236 self.flexible = yes;
237 }
238
239 pub const fn set_escape_formulas(&mut self, yes: bool) {
255 self.escape_formulas = yes;
256 }
257
258 pub fn to_string<T: Serialize + ?Sized>(&self, value: &T) -> Result<String, Error> {
262 self.to_string_ref(SerializeRef::new(&value))
263 }
264
265 pub fn to_string_with<F, T: Serialize + ?Sized>(
270 &self,
271 value: &T,
272 setup: F,
273 ) -> Result<String, Error>
274 where
275 F: FnOnce(&mut SerializeDriver<'_>),
276 {
277 let mut driver = SerializeDriver::new(&value);
278 setup(&mut driver);
279 self.apply_context(&mut driver);
280 let mut out = Vec::new();
281 self.write_whole(&mut WriterState::default(), &mut driver, true, &mut out)?;
282 Ok(into_string(out))
283 }
284
285 fn to_string_ref(&self, value: SerializeRef<'_>) -> Result<String, Error> {
291 let mut driver = SerializeDriver::from_ref(value);
292 self.apply_context(&mut driver);
293 let mut out = Vec::new();
294 self.write_whole(&mut WriterState::default(), &mut driver, true, &mut out)?;
295 Ok(into_string(out))
296 }
297
298 pub(crate) fn write(
305 &self,
306 state: &mut WriterState,
307 driver: &mut SerializeDriver<'_>,
308 document: bool,
309 out: &mut Vec<u8>,
310 limit: usize,
311 ) -> Result<bool, Error> {
312 let drive: DriveFn = if limit == usize::MAX {
313 drive_whole
314 } else {
315 drive_partial
316 };
317 self.write_with(state, driver, document, out, limit, drive)
318 }
319
320 pub(crate) fn write_whole(
326 &self,
327 state: &mut WriterState,
328 driver: &mut SerializeDriver<'_>,
329 document: bool,
330 out: &mut Vec<u8>,
331 ) -> Result<(), Error> {
332 self.write_with(state, driver, document, out, usize::MAX, drive_whole)
333 .map(|_| ())
334 }
335
336 fn write_with(
338 &self,
339 state: &mut WriterState,
340 driver: &mut SerializeDriver<'_>,
341 document: bool,
342 out: &mut Vec<u8>,
343 limit: usize,
344 drive: DriveFn,
345 ) -> Result<bool, Error> {
346 let dialect = match state.dialect {
347 Some(ref dialect) => dialect,
348 None => state.dialect.insert(Dialect::new(
349 self.delimiter,
350 self.quote,
351 self.double_quote,
352 self.escape,
353 self.terminator,
354 None,
355 )?),
356 };
357 let mut writer = RecordWriter {
358 encoder: FieldEncoder {
359 config: self,
360 dialect,
361 bytes: BytesFormat::of(driver.state()),
362 plain: matches!(self.quote_style, QuoteStyle::Necessary | QuoteStyle::Never)
363 && self.nulls == Nulls::None
364 && !self.escape_formulas,
365 },
366 names: state.names.take(),
367 len: state.len,
368 document,
369 direct: false,
370 is_map: false,
371 fields: 0,
372 record_start: 0,
373 field_ends: core::mem::take(&mut state.buffers.field_ends),
374 record: core::mem::take(&mut state.buffers.record),
375 scratch: Scratch::new(core::mem::take(&mut state.buffers.scratch)),
376 open: false,
377 limit,
378 out,
379 };
380 let had_names = writer.names.is_some();
381 let rv = drive(driver, &mut writer);
382 if rv.is_ok() || had_names {
385 state.names = writer.names;
386 }
387 if rv.is_ok() {
388 state.len = writer.len;
389 }
390 state.buffers = Buffers {
392 field_ends: writer.field_ends,
393 record: writer.record,
394 scratch: writer.scratch.bytes,
395 };
396 rv
397 }
398}
399
400#[derive(Debug, Clone)]
404#[must_use]
405pub struct SerializerConfigBuilder {
406 value: SerializerConfig,
407}
408
409impl SerializerConfigBuilder {
410 pub const fn new() -> SerializerConfigBuilder {
412 SerializerConfigBuilder {
413 value: SerializerConfig::new(),
414 }
415 }
416
417 pub const fn delimiter(mut self, delimiter: u8) -> SerializerConfigBuilder {
421 self.value.set_delimiter(delimiter);
422 self
423 }
424
425 pub const fn quote(mut self, quote: Option<u8>) -> SerializerConfigBuilder {
429 self.value.set_quote(quote);
430 self
431 }
432
433 pub const fn double_quote(mut self, yes: bool) -> SerializerConfigBuilder {
437 self.value.set_double_quote(yes);
438 self
439 }
440
441 pub const fn escape(mut self, escape: Escape) -> SerializerConfigBuilder {
445 self.value.set_escape(escape);
446 self
447 }
448
449 pub const fn terminator(mut self, terminator: Terminator) -> SerializerConfigBuilder {
453 self.value.set_terminator(terminator);
454 self
455 }
456
457 pub const fn quote_style(mut self, style: QuoteStyle) -> SerializerConfigBuilder {
461 self.value.set_quote_style(style);
462 self
463 }
464
465 pub const fn headers(mut self, yes: bool) -> SerializerConfigBuilder {
469 self.value.set_headers(yes);
470 self
471 }
472
473 pub const fn columns(mut self, names: &'static [&'static str]) -> SerializerConfigBuilder {
477 self.value.set_columns(names);
478 self
479 }
480
481 pub const fn nulls(mut self, nulls: Nulls) -> SerializerConfigBuilder {
485 self.value.set_nulls(nulls);
486 self
487 }
488
489 pub const fn flexible(mut self, yes: bool) -> SerializerConfigBuilder {
493 self.value.set_flexible(yes);
494 self
495 }
496
497 pub const fn escape_formulas(mut self, yes: bool) -> SerializerConfigBuilder {
501 self.value.set_escape_formulas(yes);
502 self
503 }
504
505 pub fn context(mut self, context: deser_core::Context) -> SerializerConfigBuilder {
509 self.value.set_context(context);
510 self
511 }
512
513 pub const fn build(self) -> SerializerConfig {
515 let value = unsafe { core::ptr::read(&self.value) };
519 core::mem::forget(self);
520 value
521 }
522}
523
524impl Default for SerializerConfigBuilder {
525 fn default() -> SerializerConfigBuilder {
526 SerializerConfigBuilder::new()
527 }
528}
529
530type DriveFn = fn(&mut SerializeDriver<'_>, &mut RecordWriter<'_>) -> Result<bool, Error>;
532
533fn drive_whole(
535 driver: &mut SerializeDriver<'_>,
536 writer: &mut RecordWriter<'_>,
537) -> Result<bool, Error> {
538 driver
539 .drive(|event, state| writer.event(event, state))
540 .map(|()| true)
541}
542
543fn drive_partial(
545 driver: &mut SerializeDriver<'_>,
546 writer: &mut RecordWriter<'_>,
547) -> Result<bool, Error> {
548 driver.drive_until(writer)
549}
550
551#[derive(Clone, Default)]
553struct Buffers {
554 field_ends: Vec<usize>,
555 record: Record,
556 scratch: Vec<u8>,
557}
558
559impl core::fmt::Debug for Buffers {
560 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
561 f.debug_struct("Buffers").finish_non_exhaustive()
562 }
563}
564
565#[derive(Debug, Clone, Default)]
570pub(crate) struct WriterState {
571 names: Option<Vec<String>>,
572 len: Option<usize>,
574 dialect: Option<Dialect>,
576 buffers: Buffers,
577}
578
579impl WriterState {
580 fn with_headers(names: Vec<String>) -> WriterState {
583 WriterState {
584 len: Some(names.len()),
585 names: Some(names),
586 dialect: None,
587 buffers: Buffers::default(),
588 }
589 }
590}
591
592#[derive(Debug, Clone)]
619pub struct Serializer {
620 config: SerializerConfig,
621 state: WriterState,
622 out: Vec<u8>,
623 document: bool,
625 in_progress: bool,
627}
628
629impl Default for Serializer {
630 fn default() -> Serializer {
631 Serializer::new()
632 }
633}
634
635impl Serializer {
636 pub fn new() -> Serializer {
638 Serializer::with_config(SerializerConfig::new())
639 }
640
641 pub fn with_config(config: SerializerConfig) -> Serializer {
643 Serializer::with_state(config, WriterState::default(), false)
644 }
645
646 pub fn with_headers<I, S>(config: SerializerConfig, names: I) -> Serializer
662 where
663 I: IntoIterator<Item = S>,
664 S: Into<String>,
665 {
666 let names = names.into_iter().map(Into::into).collect();
667 Serializer::with_state(config, WriterState::with_headers(names), false)
668 }
669
670 pub fn document(config: SerializerConfig) -> Serializer {
686 Serializer::with_state(config, WriterState::default(), true)
687 }
688
689 fn with_state(config: SerializerConfig, state: WriterState, document: bool) -> Serializer {
690 Serializer {
691 config,
692 state,
693 out: Vec::new(),
694 document,
695 in_progress: false,
696 }
697 }
698
699 pub fn config(&self) -> &SerializerConfig {
701 &self.config
702 }
703
704 pub fn headers(&self) -> Option<&[String]> {
709 self.state.names.as_deref()
710 }
711
712 pub fn serialize<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
717 ser::Serializer::serialize(self, value)
718 }
719
720 pub fn serialize_with<F, T: Serialize + ?Sized>(
725 &mut self,
726 value: &T,
727 setup: F,
728 ) -> Result<(), Error>
729 where
730 F: FnOnce(&mut SerializeDriver<'_>),
731 {
732 ser::Serializer::serialize_with(self, value, setup)
733 }
734
735 pub fn as_str(&self) -> &str {
737 unsafe { core::str::from_utf8_unchecked(&self.out) }
739 }
740
741 pub fn finish(self) -> String {
743 into_string(self.out)
744 }
745}
746
747impl ser::Serializer for Serializer {
748 fn drive(&mut self, driver: &mut SerializeDriver<'_>) -> Result<(), Error> {
749 if !self.config.context.is_empty() {
750 driver.set_default_context(self.config.context.clone());
751 }
752 if self.in_progress {
753 return Err(Error::in_progress());
754 }
755 let len = self.out.len();
756 match self
757 .config
758 .write_whole(&mut self.state, driver, self.document, &mut self.out)
759 {
760 Ok(()) => Ok(()),
761 Err(err) => {
762 self.out.truncate(len);
763 Err(err)
764 }
765 }
766 }
767}
768
769impl ser::StreamSerializer for Serializer {
770 fn output(&self) -> &[u8] {
771 &self.out
772 }
773
774 fn clear_output(&mut self) {
775 self.out.clear();
776 }
777
778 fn supports_partial(&self) -> bool {
780 self.document
781 }
782
783 fn drive_partial(
784 &mut self,
785 driver: &mut SerializeDriver<'_>,
786 limit: usize,
787 ) -> Result<bool, Error> {
788 if !self.config.context.is_empty() {
789 driver.set_default_context(self.config.context.clone());
790 }
791 if !self.document || (limit == usize::MAX && !self.in_progress) {
792 ser::Serializer::drive(self, driver)?;
793 return Ok(true);
794 }
795 let len = self.out.len();
796 match self
797 .config
798 .write(&mut self.state, driver, true, &mut self.out, limit)
799 {
800 Ok(done) => {
801 self.in_progress = !done;
802 Ok(done)
803 }
804 Err(err) => {
805 self.out.truncate(len);
808 Err(err)
809 }
810 }
811 }
812
813 fn in_progress(&self) -> bool {
814 self.in_progress
815 }
816}
817
818#[cfg(feature = "io")]
819impl SerializerConfig {
820 pub fn writer<W: std::io::Write>(&self, writer: W) -> deser_core::io::Writer<W, Serializer> {
842 deser_core::io::Writer::new(writer, Serializer::with_config(self.clone()))
843 }
844
845 pub fn to_writer<W: std::io::Write, T: Serialize + ?Sized>(
849 &self,
850 writer: W,
851 value: &T,
852 ) -> Result<(), Error> {
853 deser_core::io::to_writer(writer, Serializer::document(self.clone()), value)
854 }
855}
856
857#[cfg(feature = "io")]
870pub fn to_writer<W: std::io::Write, T: Serialize + ?Sized>(
871 writer: W,
872 value: &T,
873) -> Result<(), Error> {
874 SerializerConfig::new().to_writer(writer, value)
875}
876
877fn into_string(out: Vec<u8>) -> String {
882 debug_assert!(core::str::from_utf8(&out).is_ok());
883 unsafe { String::from_utf8_unchecked(out) }
885}
886
887pub fn to_string<T: Serialize + ?Sized>(value: &T) -> Result<String, Error> {
913 SerializerConfig::new().to_string(value)
914}
915
916#[derive(Clone, Default)]
918struct Record {
919 keys: Vec<u8>,
921 key_ends: Vec<usize>,
922 fields: Vec<u8>,
924 field_ends: Vec<usize>,
925}
926
927impl Record {
928 fn clear(&mut self) {
929 self.keys.clear();
930 self.key_ends.clear();
931 self.fields.clear();
932 self.field_ends.clear();
933 }
934
935 fn key(&self, index: usize) -> &[u8] {
936 let start = if index == 0 {
937 0
938 } else {
939 self.key_ends[index - 1]
940 };
941 &self.keys[start..self.key_ends[index]]
942 }
943
944 fn field(&self, index: usize) -> &[u8] {
945 let start = if index == 0 {
946 0
947 } else {
948 self.field_ends[index - 1]
949 };
950 &self.fields[start..self.field_ends[index]]
951 }
952}
953
954struct RecordWriter<'a> {
961 encoder: FieldEncoder<'a>,
962 names: Option<Vec<String>>,
963 len: Option<usize>,
964 document: bool,
965 direct: bool,
967 is_map: bool,
968 fields: usize,
970 record_start: usize,
972 field_ends: Vec<usize>,
975 record: Record,
977 scratch: Scratch,
979 open: bool,
981 limit: usize,
983 out: &'a mut Vec<u8>,
984}
985
986impl EventSink for RecordWriter<'_> {
987 #[inline]
988 fn event(
989 &mut self,
990 event: Event<'_>,
991 _value: SerializeRef<'_>,
992 state: &mut State,
993 ) -> Result<(), Error> {
994 RecordWriter::event(self, event, state)
995 }
996
997 #[inline]
998 fn pause(&mut self) -> bool {
999 !self.open && self.out.len() >= self.limit
1001 }
1002}
1003
1004impl RecordWriter<'_> {
1005 #[inline]
1006 fn event(&mut self, event: Event<'_>, state: &State) -> Result<(), Error> {
1007 if let Event::Atom(ref atom) = event
1009 && state.depth() == usize::from(self.document) + 1
1010 {
1011 return self.atom(atom, state.is_map_key());
1012 }
1013 self.structure(event, state)
1014 }
1015
1016 fn structure(&mut self, event: Event<'_>, state: &State) -> Result<(), Error> {
1018 let depth = match event {
1021 Event::MapStart(_) | Event::SeqStart(_) => state.depth().saturating_sub(1),
1022 _ => state.depth(),
1023 };
1024 let record_depth = usize::from(self.document);
1025 match event {
1026 Event::SeqStart(_) | Event::SeqEnd if self.document && depth == 0 => {}
1027 _ if depth < record_depth => {
1028 return Err(Error::new(
1029 ErrorKind::UnsupportedType,
1030 "CSV documents are sequences of records",
1031 ));
1032 }
1033 Event::MapStart(_) | Event::SeqStart(_) if depth == record_depth => {
1034 if self.names.is_none()
1035 && let Some(columns) = self.encoder.config.columns
1036 {
1037 let names: Vec<String> = columns.iter().map(|name| name.to_string()).collect();
1038 if self.encoder.config.headers {
1039 self.write_names(&names)?;
1040 }
1041 self.names = Some(names);
1042 }
1043 self.is_map = matches!(event, Event::MapStart(_));
1044 self.open = true;
1045 self.direct = !self.is_map || self.names.is_some();
1046 self.fields = 0;
1047 self.record_start = self.out.len();
1048 self.field_ends.clear();
1049 self.record.clear();
1050 }
1051 Event::MapEnd | Event::SeqEnd if depth == record_depth => {
1052 self.open = false;
1053 self.finish_record()?
1054 }
1055 _ if depth == record_depth => {
1056 return Err(Error::new(
1057 ErrorKind::UnsupportedType,
1058 "CSV records must be maps or sequences",
1059 ));
1060 }
1061 Event::MapStart(_) | Event::SeqStart(_) | Event::MapEnd | Event::SeqEnd => {
1063 return Err(Error::new(
1064 ErrorKind::UnsupportedType,
1065 "CSV fields cannot hold maps or sequences",
1066 ));
1067 }
1068 Event::Atom(ref atom) => return self.atom(atom, state.is_map_key()),
1069 }
1070 Ok(())
1071 }
1072
1073 #[inline(always)]
1075 fn atom(&mut self, atom: &Atom<'_>, is_key: bool) -> Result<(), Error> {
1076 if is_key {
1077 return self.key(atom);
1078 }
1079 let text = self.encoder.text(atom, &mut self.scratch)?;
1080 if self.direct {
1081 if self.fields > 0 {
1082 self.out.push(self.encoder.dialect.delimiter);
1083 }
1084 self.encoder.encode(text, self.out)?;
1085 self.field_ends.push(self.out.len());
1086 } else {
1087 self.encoder.encode(text, &mut self.record.fields)?;
1088 self.record.field_ends.push(self.record.fields.len());
1089 }
1090 self.fields += 1;
1091 Ok(())
1092 }
1093
1094 #[inline(always)]
1096 fn key(&mut self, atom: &Atom<'_>) -> Result<(), Error> {
1097 if self.direct
1099 && let Atom::Str(key) = atom
1100 && let Some(names) = &self.names
1101 && let Some(name) = names.get(self.fields)
1102 && same_key(name.as_bytes(), key.as_bytes())
1103 {
1104 return Ok(());
1105 }
1106 self.other_key(atom)
1107 }
1108
1109 #[inline(never)]
1111 fn other_key(&mut self, atom: &Atom<'_>) -> Result<(), Error> {
1112 let key = match atom {
1113 Atom::Null | Atom::Bytes(_) => None,
1114 atom => self.encoder.text(atom, &mut self.scratch)?,
1115 };
1116 let key = key.ok_or_else(unsupported_key)?;
1117 if !self.direct {
1118 self.record.keys.extend_from_slice(key.bytes);
1119 } else {
1120 let names = self.names.as_deref().unwrap_or_default();
1121 if let Some(name) = names.get(self.fields)
1122 && same_key(name.as_bytes(), key.bytes)
1123 {
1124 return Ok(());
1125 }
1126 let key = key.bytes.to_vec();
1127 self.collect();
1128 self.record.keys.extend_from_slice(&key);
1129 }
1130 self.record.key_ends.push(self.record.keys.len());
1131 Ok(())
1132 }
1133
1134 fn collect(&mut self) {
1136 let names = self.names.as_deref().unwrap_or_default();
1137 let mut start = self.record_start;
1138 for (index, &end) in self.field_ends.iter().enumerate() {
1139 if index > 0 {
1140 start += 1;
1142 }
1143 self.record.fields.extend_from_slice(&self.out[start..end]);
1144 self.record.field_ends.push(self.record.fields.len());
1145 self.record.keys.extend_from_slice(names[index].as_bytes());
1146 self.record.key_ends.push(self.record.keys.len());
1147 start = end;
1148 }
1149 self.out.truncate(self.record_start);
1150 self.direct = false;
1151 }
1152
1153 fn finish_record(&mut self) -> Result<(), Error> {
1155 let start = self.record_start;
1156 if !self.is_map {
1157 self.check_len(self.fields)?;
1158 return self.terminate(self.fields, start);
1159 }
1160
1161 if self.direct {
1162 let len = self.names.as_ref().map_or(0, Vec::len);
1164 for column in self.fields..len {
1165 if column > 0 {
1166 self.out.push(self.encoder.dialect.delimiter);
1167 }
1168 self.encoder.encode(None, self.out)?;
1169 }
1170 self.check_len(len)?;
1171 return self.terminate(len, start);
1172 }
1173
1174 let count = self.record.field_ends.len();
1175 if self.names.is_none() {
1176 let names: Vec<String> = (0..count)
1178 .map(|index| String::from_utf8_lossy(self.record.key(index)).into_owned())
1179 .collect();
1180 if self.encoder.config.headers {
1181 self.write_names(&names)?;
1182 }
1183 self.names = Some(names);
1184 }
1185 let len = self.names.as_ref().map_or(0, Vec::len);
1186 self.check_len(len)?;
1187 let names = self.names.as_ref().unwrap();
1188 let start = self.out.len();
1189 let mut order = vec![None; len];
1190 for index in 0..count {
1191 let key = String::from_utf8_lossy(self.record.key(index));
1192 match names.iter().position(|name| *name == key) {
1193 Some(column) if order[column].is_none() => order[column] = Some(index),
1194 Some(_) => {
1195 return Err(Error::new(
1196 ErrorKind::DuplicateKey,
1197 format!("duplicate field `{}`", key),
1198 ));
1199 }
1200 None => {
1201 return Err(Error::new(
1202 ErrorKind::UnknownField,
1203 format!("field `{}` is not a column", key),
1204 ));
1205 }
1206 }
1207 }
1208 for (column, index) in order.into_iter().enumerate() {
1209 if column > 0 {
1210 self.out.push(self.encoder.dialect.delimiter);
1211 }
1212 match index {
1213 Some(index) => self.out.extend_from_slice(self.record.field(index)),
1214 None => self.encoder.encode(None, self.out)?,
1216 }
1217 }
1218 self.terminate(len, start)
1219 }
1220
1221 fn check_len(&mut self, len: usize) -> Result<(), Error> {
1223 match self.len {
1224 Some(expected) if expected != len && !self.encoder.config.flexible => Err(Error::new(
1225 ErrorKind::WrongLength,
1226 format!("record has {} fields, expected {}", len, expected),
1227 )),
1228 Some(_) => Ok(()),
1229 None => {
1230 self.len = Some(len);
1231 Ok(())
1232 }
1233 }
1234 }
1235
1236 fn terminate(&mut self, len: usize, start: usize) -> Result<(), Error> {
1239 if len == 1 && self.out.len() == start {
1240 match self.encoder.dialect.quote {
1242 Some(quote) => self.out.extend_from_slice(&[quote, quote]),
1243 None => {
1244 return Err(Error::new(
1245 ErrorKind::InvalidValue,
1246 "a record with a single empty field needs quotes",
1247 ));
1248 }
1249 }
1250 }
1251 match self.encoder.config.terminator {
1252 Terminator::Newline => self.out.push(b'\n'),
1253 Terminator::CrLf => self.out.extend_from_slice(b"\r\n"),
1254 Terminator::Byte(byte) => self.out.push(byte),
1255 }
1256 Ok(())
1257 }
1258
1259 fn write_names(&mut self, names: &[String]) -> Result<(), Error> {
1261 let start = self.out.len();
1262 for (index, name) in names.iter().enumerate() {
1263 if index > 0 {
1264 self.out.push(self.encoder.dialect.delimiter);
1265 }
1266 let text = Text {
1267 bytes: name.as_bytes(),
1268 numeric: false,
1269 };
1270 self.encoder.encode(Some(text), self.out)?;
1271 }
1272 self.terminate(names.len(), start)
1273 }
1274}
1275
1276#[derive(Clone, Copy)]
1278struct Text<'a> {
1279 bytes: &'a [u8],
1280 numeric: bool,
1281}
1282
1283#[derive(Clone, Copy)]
1285struct FieldEncoder<'a> {
1286 config: &'a SerializerConfig,
1287 dialect: &'a Dialect,
1288 bytes: BytesFormat,
1290 plain: bool,
1294}
1295
1296impl FieldEncoder<'_> {
1297 #[inline(always)]
1299 fn encode(&self, text: Option<Text<'_>>, out: &mut Vec<u8>) -> Result<(), Error> {
1300 if self.plain
1302 && let Some(Text { bytes, .. }) = text
1303 && !self.dialect.has_special(bytes)
1304 {
1305 push_bytes(out, bytes);
1306 return Ok(());
1307 }
1308 self.encode_special(text, out)
1309 }
1310
1311 #[inline(never)]
1313 fn encode_special(&self, text: Option<Text<'_>>, out: &mut Vec<u8>) -> Result<(), Error> {
1314 let config = self.config;
1315 let Some(Text { bytes, numeric }) = text else {
1316 if let Nulls::Text(null) = config.nulls {
1317 out.extend_from_slice(null.as_bytes());
1318 }
1319 return Ok(());
1320 };
1321 let reads_as_null = match config.nulls {
1322 Nulls::None => false,
1323 Nulls::Empty => bytes.is_empty(),
1324 Nulls::Text(null) => bytes == null.as_bytes(),
1325 };
1326 let formula = config.escape_formulas
1329 && !numeric
1330 && matches!(
1331 bytes.first(),
1332 Some(b'=' | b'+' | b'-' | b'@' | b'\t' | b'\r')
1333 );
1334 let has_special = self.dialect.has_special(bytes);
1335 let quote_style = match config.quote_style {
1336 QuoteStyle::Always => true,
1337 QuoteStyle::NonNumeric => !numeric,
1338 QuoteStyle::Necessary | QuoteStyle::Never => false,
1339 };
1340 if !quote_style && !has_special && !reads_as_null && !formula {
1341 out.extend_from_slice(bytes);
1342 return Ok(());
1343 }
1344
1345 let prefix: &[u8] = if formula { b"'" } else { b"" };
1346 let escape = config.escape.byte();
1347 let prefix_is_special = formula && self.dialect.is_special(b'\'');
1348 let quoted = quote_style
1351 || (formula && self.dialect.quote.is_some() && config.quote_style != QuoteStyle::Never)
1352 || (escape.is_none() && (has_special || prefix_is_special || reads_as_null))
1353 || (reads_as_null && bytes.is_empty());
1354 let text = prefix.iter().chain(bytes).copied();
1355
1356 if !quoted {
1357 for (index, byte) in text.enumerate() {
1358 if self.dialect.is_special(byte) || (index == 0 && reads_as_null) {
1359 out.push(escape.unwrap_or(b'\\'));
1361 out.push(self.escaped(byte));
1362 } else {
1363 out.push(byte);
1364 }
1365 }
1366 return Ok(());
1367 }
1368
1369 let quote = match self.dialect.quote {
1370 Some(quote) if config.quote_style != QuoteStyle::Never => quote,
1371 _ => {
1372 return Err(Error::new(
1373 ErrorKind::InvalidValue,
1374 format!(
1375 "field {:?} needs to be quoted",
1376 String::from_utf8_lossy(bytes)
1377 ),
1378 ));
1379 }
1380 };
1381 out.push(quote);
1382 if formula {
1383 self.push_quoted(b'\'', quote, out)?;
1384 }
1385 let mut bytes = bytes;
1386 loop {
1387 let run = bytes
1389 .iter()
1390 .position(|&b| b == quote || Some(b) == escape)
1391 .unwrap_or(bytes.len());
1392 out.extend_from_slice(&bytes[..run]);
1393 let Some((&byte, rest)) = bytes[run..].split_first() else {
1394 break;
1395 };
1396 bytes = rest;
1397 self.push_quoted(byte, quote, out)?;
1398 }
1399 out.push(quote);
1400 Ok(())
1401 }
1402
1403 fn push_quoted(&self, byte: u8, quote: u8, out: &mut Vec<u8>) -> Result<(), Error> {
1405 let escape = self.config.escape.byte();
1406 if byte == quote && self.config.double_quote {
1407 out.extend_from_slice(&[quote, quote]);
1408 } else if byte == quote || Some(byte) == escape {
1409 match escape {
1410 Some(escape) => out.extend_from_slice(&[escape, self.escaped(byte)]),
1411 None => {
1412 return Err(Error::new(
1413 ErrorKind::InvalidValue,
1414 "quotes in quoted fields need to be doubled or escaped",
1415 ));
1416 }
1417 }
1418 } else {
1419 out.push(byte);
1420 }
1421 Ok(())
1422 }
1423
1424 fn escaped(&self, byte: u8) -> u8 {
1426 match (self.config.escape, byte) {
1427 (Escape::Backslash, b'\t') => b't',
1428 (Escape::Backslash, b'\n') => b'n',
1429 (Escape::Backslash, b'\r') => b'r',
1430 (_, byte) => byte,
1431 }
1432 }
1433
1434 #[inline(always)]
1438 fn text<'a>(
1439 &self,
1440 atom: &'a Atom<'_>,
1441 scratch: &'a mut Scratch,
1442 ) -> Result<Option<Text<'a>>, Error> {
1443 let (bytes, numeric) = match *atom {
1444 Atom::Str(ref value) | Atom::Lexical(ref value) => (value.as_bytes(), false),
1445 Atom::Null => return Ok(None),
1446 Atom::Bool(value) => (if value { &b"true"[..] } else { b"false" }, false),
1447 Atom::U64(value) => (scratch.int.format(value).as_bytes(), true),
1449 Atom::I64(value) => (scratch.int.format(value).as_bytes(), true),
1450 Atom::F64(value) => (scratch.float(value), true),
1451 Atom::F32(value) => (scratch.float(value), true),
1452 _ => return self.other_text(atom, &mut scratch.bytes),
1453 };
1454 Ok(Some(Text { bytes, numeric }))
1455 }
1456
1457 #[inline(never)]
1459 fn other_text<'a>(
1460 &self,
1461 atom: &'a Atom<'_>,
1462 scratch: &'a mut Vec<u8>,
1463 ) -> Result<Option<Text<'a>>, Error> {
1464 scratch.clear();
1465 let numeric = match *atom {
1466 Atom::Char(value) => {
1467 scratch.extend_from_slice(value.encode_utf8(&mut [0; 4]).as_bytes());
1468 false
1469 }
1470 Atom::Bytes(ref bytes) => {
1471 let format = bytes.fallback.copied().unwrap_or(self.bytes);
1472 let text = format
1473 .encode(bytes)
1474 .or_else(|| BytesFormat::BASE64.encode(bytes))
1475 .unwrap_or_default();
1476 scratch.extend_from_slice(text.as_bytes());
1477 false
1478 }
1479 Atom::Ext(ref ext) => {
1480 if let Some(number) = ext.downcast_value_ref::<Number>() {
1481 scratch.extend_from_slice(number.as_str().as_bytes());
1483 } else if let Some(value) = ext.downcast_ref::<u128>() {
1484 let _ = write!(ByteWriter(scratch), "{}", value);
1485 } else if let Some(value) = ext.downcast_ref::<i128>() {
1486 let _ = write!(ByteWriter(scratch), "{}", value);
1487 } else {
1488 return match ext.fallback() {
1489 Atom::Ext(_) => Err(Error::new(
1490 ErrorKind::UnsupportedType,
1491 format!("CSV does not support {}", ext.name()),
1492 )),
1493 fallback => {
1494 let mut inner = Scratch::new(Vec::new());
1495 let numeric = match self.text(&fallback, &mut inner)? {
1496 Some(text) => {
1497 let numeric = text.numeric;
1498 scratch.extend_from_slice(text.bytes);
1499 numeric
1500 }
1501 None => return Ok(None),
1502 };
1503 Ok(Some(Text {
1504 bytes: scratch,
1505 numeric,
1506 }))
1507 }
1508 };
1509 }
1510 true
1511 }
1512 Atom::Implicit(ref value) => {
1514 let mut inner = Scratch::new(Vec::new());
1515 return Ok(match self.text(&value.value().to_atom(), &mut inner)? {
1516 Some(text) => {
1517 let numeric = text.numeric;
1518 scratch.extend_from_slice(text.bytes);
1519 Some(Text {
1520 bytes: scratch,
1521 numeric,
1522 })
1523 }
1524 None => None,
1525 });
1526 }
1527 _ => {
1528 return Err(Error::new(
1529 ErrorKind::UnsupportedType,
1530 format!("CSV does not support {}", atom.name()),
1531 ));
1532 }
1533 };
1534 Ok(Some(Text {
1535 bytes: scratch,
1536 numeric,
1537 }))
1538 }
1539}
1540
1541struct ByteWriter<'a>(&'a mut Vec<u8>);
1543
1544impl fmt::Write for ByteWriter<'_> {
1545 fn write_str(&mut self, s: &str) -> fmt::Result {
1546 self.0.extend_from_slice(s.as_bytes());
1547 Ok(())
1548 }
1549}
1550
1551struct Scratch {
1553 bytes: Vec<u8>,
1555 int: itoa::Buffer,
1556 float: zmij::Buffer,
1557}
1558
1559impl Scratch {
1560 fn new(bytes: Vec<u8>) -> Scratch {
1561 Scratch {
1562 bytes,
1563 int: itoa::Buffer::new(),
1564 float: zmij::Buffer::new(),
1565 }
1566 }
1567
1568 #[inline]
1571 fn float<F: zmij::Float>(&mut self, value: F) -> &[u8] {
1572 self.float.format(value).as_bytes()
1574 }
1575}
1576
1577#[inline(always)]
1582fn push_bytes(out: &mut Vec<u8>, bytes: &[u8]) {
1583 crate::copy::extend(out, bytes);
1584}
1585
1586#[inline(always)]
1591fn same_key(name: &[u8], key: &[u8]) -> bool {
1592 let len = name.len();
1593 if len != key.len() {
1594 return false;
1595 }
1596 match len {
1597 0 => true,
1598 1..=3 => {
1600 name[0] == key[0] && name[len / 2] == key[len / 2] && name[len - 1] == key[len - 1]
1601 }
1602 4..=8 => {
1603 load_u32(name, 0) == load_u32(key, 0)
1604 && load_u32(name, len - 4) == load_u32(key, len - 4)
1605 }
1606 9..=16 => {
1607 load_u64(name, 0) == load_u64(key, 0)
1608 && load_u64(name, len - 8) == load_u64(key, len - 8)
1609 }
1610 _ => name == key,
1611 }
1612}
1613
1614#[cold]
1615fn unsupported_key() -> Error {
1616 Error::new(
1617 ErrorKind::UnsupportedType,
1618 "the keys of records must be strings, numbers or booleans",
1619 )
1620}
1621
1622#[cfg(test)]
1623mod tests {
1624 use super::*;
1625
1626 #[test]
1627 fn test_push_bytes() {
1628 let text: Vec<u8> = (b'a'..=b'z').chain(b'A'..=b'Z').collect();
1629 for len in 0..=text.len() {
1630 for prefix in [0, 1, 7] {
1631 let mut out = vec![b'-'; prefix];
1632 push_bytes(&mut out, &text[..len]);
1633 assert_eq!(&out[prefix..], &text[..len]);
1634 assert_eq!(out.len(), prefix + len);
1635 }
1636 }
1637 }
1638
1639 #[test]
1640 fn test_same_key() {
1641 let text: Vec<u8> = (b'a'..=b'z').chain(b'A'..=b'Z').collect();
1642 for len in 0..=text.len() {
1643 let name = &text[..len];
1644 assert!(same_key(name, &text[..len]));
1645 if len > 0 {
1646 assert!(!same_key(name, &text[..len - 1]));
1647 assert!(!same_key(&text[..len - 1], name));
1648 }
1649 for pos in 0..len {
1650 let mut key = name.to_vec();
1651 key[pos] ^= 1;
1652 assert!(!same_key(name, &key), "{:?}", key);
1653 }
1654 }
1655 }
1656}