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};
14
15#[inline(always)]
17fn load_u128(bytes: &[u8], pos: usize) -> u128 {
18 u128::from_ne_bytes(*bytes[pos..].first_chunk().unwrap())
19}
20use crate::{Escape, Nulls, QuoteStyle, Terminator};
21
22#[derive(Debug, Clone, PartialEq, Eq)]
57pub struct SerializerConfig {
58 delimiter: u8,
59 quote: Option<u8>,
60 double_quote: bool,
61 escape: Escape,
62 terminator: Terminator,
63 quote_style: QuoteStyle,
64 headers: bool,
65 columns: Option<&'static [&'static str]>,
66 nulls: Nulls,
67 flexible: bool,
68 escape_formulas: bool,
69 context: deser_core::Context,
70}
71
72impl Default for SerializerConfig {
73 fn default() -> SerializerConfig {
74 SerializerConfig::new()
75 }
76}
77
78impl SerializerConfig {
79 pub const fn new() -> SerializerConfig {
81 SerializerConfig {
82 delimiter: b',',
83 quote: Some(b'"'),
84 double_quote: true,
85 escape: Escape::None,
86 terminator: Terminator::Newline,
87 quote_style: QuoteStyle::Necessary,
88 headers: true,
89 columns: None,
90 nulls: Nulls::None,
91 flexible: false,
92 escape_formulas: false,
93 context: deser_core::Context::new(),
94 }
95 }
96
97 pub const fn builder() -> SerializerConfigBuilder {
99 SerializerConfigBuilder::new()
100 }
101
102 pub const fn into_builder(self) -> SerializerConfigBuilder {
104 SerializerConfigBuilder { value: self }
105 }
106
107 pub fn set_context(&mut self, context: deser_core::Context) {
115 self.context = context;
116 }
117
118 pub fn context(&self) -> &deser_core::Context {
120 &self.context
121 }
122
123 #[inline]
125 fn apply_context(&self, driver: &mut SerializeDriver<'_>) {
126 if !self.context.is_empty() {
127 driver.set_default_context(self.context.clone());
128 }
129 }
130
131 pub const fn tsv() -> SerializerConfig {
144 let mut config = SerializerConfig::new();
145 config.set_delimiter(b'\t');
146 config.set_quote(None);
147 config.set_escape(Escape::Backslash);
148 config.set_nulls(Nulls::Text("\\N"));
149 config
150 }
151
152 pub const fn set_delimiter(&mut self, delimiter: u8) {
154 self.delimiter = delimiter;
155 }
156
157 pub const fn set_quote(&mut self, quote: Option<u8>) {
162 self.quote = quote;
163 }
164
165 pub const fn set_double_quote(&mut self, yes: bool) {
169 self.double_quote = yes;
170 }
171
172 pub const fn set_escape(&mut self, escape: Escape) {
177 self.escape = escape;
178 }
179
180 pub const fn set_terminator(&mut self, terminator: Terminator) {
182 self.terminator = terminator;
183 }
184
185 pub const fn set_quote_style(&mut self, style: QuoteStyle) {
187 self.quote_style = style;
188 }
189
190 pub const fn set_headers(&mut self, yes: bool) {
197 self.headers = yes;
198 }
199
200 pub const fn set_columns(&mut self, names: &'static [&'static str]) {
227 self.columns = Some(names);
228 }
229
230 pub const fn set_nulls(&mut self, nulls: Nulls) {
236 self.nulls = nulls;
237 }
238
239 pub const fn set_flexible(&mut self, yes: bool) {
242 self.flexible = yes;
243 }
244
245 pub const fn set_escape_formulas(&mut self, yes: bool) {
261 self.escape_formulas = yes;
262 }
263
264 pub fn to_string<T: Serialize + ?Sized>(&self, value: &T) -> Result<String, Error> {
268 self.to_string_ref(SerializeRef::new(&value))
269 }
270
271 pub fn to_string_with<F, T: Serialize + ?Sized>(
276 &self,
277 value: &T,
278 setup: F,
279 ) -> Result<String, Error>
280 where
281 F: FnOnce(&mut SerializeDriver<'_>),
282 {
283 let mut driver = SerializeDriver::new(&value);
284 setup(&mut driver);
285 self.apply_context(&mut driver);
286 let mut out = Vec::new();
287 self.write_whole(&mut WriterState::default(), &mut driver, true, &mut out)?;
288 Ok(into_string(out))
289 }
290
291 fn to_string_ref(&self, value: SerializeRef<'_>) -> Result<String, Error> {
297 let mut driver = SerializeDriver::from_ref(value);
298 self.apply_context(&mut driver);
299 let mut out = Vec::new();
300 self.write_whole(&mut WriterState::default(), &mut driver, true, &mut out)?;
301 Ok(into_string(out))
302 }
303
304 pub(crate) fn write(
311 &self,
312 state: &mut WriterState,
313 driver: &mut SerializeDriver<'_>,
314 document: bool,
315 out: &mut Vec<u8>,
316 limit: usize,
317 ) -> Result<bool, Error> {
318 let drive: DriveFn = if limit == usize::MAX {
319 drive_whole
320 } else {
321 drive_partial
322 };
323 self.write_with(state, driver, document, out, limit, drive)
324 }
325
326 pub(crate) fn write_whole(
332 &self,
333 state: &mut WriterState,
334 driver: &mut SerializeDriver<'_>,
335 document: bool,
336 out: &mut Vec<u8>,
337 ) -> Result<(), Error> {
338 self.write_with(state, driver, document, out, usize::MAX, drive_whole)
339 .map(|_| ())
340 }
341
342 fn write_with(
344 &self,
345 state: &mut WriterState,
346 driver: &mut SerializeDriver<'_>,
347 document: bool,
348 out: &mut Vec<u8>,
349 limit: usize,
350 drive: DriveFn,
351 ) -> Result<bool, Error> {
352 let dialect = match state.dialect {
353 Some(ref dialect) => dialect,
354 None => state.dialect.insert(Dialect::new(
355 self.delimiter,
356 self.quote,
357 self.double_quote,
358 self.escape,
359 self.terminator,
360 None,
361 )?),
362 };
363 let mut writer = RecordWriter {
364 encoder: FieldEncoder {
365 config: self,
366 dialect,
367 bytes: BytesFormat::of(driver.state()),
368 plain: matches!(self.quote_style, QuoteStyle::Necessary | QuoteStyle::Never)
369 && self.nulls == Nulls::None
370 && !self.escape_formulas,
371 },
372 names: state.names.take(),
373 len: state.len,
374 document,
375 direct: false,
376 is_map: false,
377 fields: 0,
378 record_start: 0,
379 field_ends: core::mem::take(&mut state.buffers.field_ends),
380 record: core::mem::take(&mut state.buffers.record),
381 scratch: Scratch::new(core::mem::take(&mut state.buffers.scratch)),
382 open: false,
383 limit,
384 out,
385 };
386 let had_names = writer.names.is_some();
387 let rv = drive(driver, &mut writer);
388 if rv.is_ok() || had_names {
391 state.names = writer.names;
392 }
393 if rv.is_ok() {
394 state.len = writer.len;
395 }
396 state.buffers = Buffers {
398 field_ends: writer.field_ends,
399 record: writer.record,
400 scratch: writer.scratch.bytes,
401 };
402 rv
403 }
404}
405
406#[derive(Debug, Clone)]
410#[must_use]
411pub struct SerializerConfigBuilder {
412 value: SerializerConfig,
413}
414
415impl SerializerConfigBuilder {
416 pub const fn new() -> SerializerConfigBuilder {
418 SerializerConfigBuilder {
419 value: SerializerConfig::new(),
420 }
421 }
422
423 pub const fn delimiter(mut self, delimiter: u8) -> SerializerConfigBuilder {
427 self.value.set_delimiter(delimiter);
428 self
429 }
430
431 pub const fn quote(mut self, quote: Option<u8>) -> SerializerConfigBuilder {
435 self.value.set_quote(quote);
436 self
437 }
438
439 pub const fn double_quote(mut self, yes: bool) -> SerializerConfigBuilder {
443 self.value.set_double_quote(yes);
444 self
445 }
446
447 pub const fn escape(mut self, escape: Escape) -> SerializerConfigBuilder {
451 self.value.set_escape(escape);
452 self
453 }
454
455 pub const fn terminator(mut self, terminator: Terminator) -> SerializerConfigBuilder {
459 self.value.set_terminator(terminator);
460 self
461 }
462
463 pub const fn quote_style(mut self, style: QuoteStyle) -> SerializerConfigBuilder {
467 self.value.set_quote_style(style);
468 self
469 }
470
471 pub const fn headers(mut self, yes: bool) -> SerializerConfigBuilder {
475 self.value.set_headers(yes);
476 self
477 }
478
479 pub const fn columns(mut self, names: &'static [&'static str]) -> SerializerConfigBuilder {
483 self.value.set_columns(names);
484 self
485 }
486
487 pub const fn nulls(mut self, nulls: Nulls) -> SerializerConfigBuilder {
491 self.value.set_nulls(nulls);
492 self
493 }
494
495 pub const fn flexible(mut self, yes: bool) -> SerializerConfigBuilder {
499 self.value.set_flexible(yes);
500 self
501 }
502
503 pub const fn escape_formulas(mut self, yes: bool) -> SerializerConfigBuilder {
507 self.value.set_escape_formulas(yes);
508 self
509 }
510
511 pub fn context(mut self, context: deser_core::Context) -> SerializerConfigBuilder {
515 self.value.set_context(context);
516 self
517 }
518
519 pub const fn build(self) -> SerializerConfig {
521 let value = unsafe { core::ptr::read(&self.value) };
525 core::mem::forget(self);
526 value
527 }
528}
529
530impl Default for SerializerConfigBuilder {
531 fn default() -> SerializerConfigBuilder {
532 SerializerConfigBuilder::new()
533 }
534}
535
536type DriveFn = fn(&mut SerializeDriver<'_>, &mut RecordWriter<'_>) -> Result<bool, Error>;
538
539fn drive_whole(
541 driver: &mut SerializeDriver<'_>,
542 writer: &mut RecordWriter<'_>,
543) -> Result<bool, Error> {
544 driver
545 .drive(|event, state| writer.event(event, state))
546 .map(|()| true)
547}
548
549fn drive_partial(
551 driver: &mut SerializeDriver<'_>,
552 writer: &mut RecordWriter<'_>,
553) -> Result<bool, Error> {
554 driver.drive_until(writer)
555}
556
557#[derive(Clone, Default)]
559struct Buffers {
560 field_ends: Vec<usize>,
561 record: Record,
562 scratch: Vec<u8>,
563}
564
565impl core::fmt::Debug for Buffers {
566 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
567 f.debug_struct("Buffers").finish_non_exhaustive()
568 }
569}
570
571#[derive(Debug, Clone, Default)]
576pub(crate) struct WriterState {
577 names: Option<Vec<String>>,
578 len: Option<usize>,
580 dialect: Option<Dialect>,
582 buffers: Buffers,
583}
584
585impl WriterState {
586 fn with_headers(names: Vec<String>) -> WriterState {
589 WriterState {
590 len: Some(names.len()),
591 names: Some(names),
592 dialect: None,
593 buffers: Buffers::default(),
594 }
595 }
596}
597
598#[derive(Debug, Clone)]
625pub struct Serializer {
626 config: SerializerConfig,
627 state: WriterState,
628 out: Vec<u8>,
629 document: bool,
631 in_progress: bool,
633}
634
635impl Default for Serializer {
636 fn default() -> Serializer {
637 Serializer::new()
638 }
639}
640
641impl Serializer {
642 pub fn new() -> Serializer {
644 Serializer::with_config(SerializerConfig::new())
645 }
646
647 pub fn with_config(config: SerializerConfig) -> Serializer {
649 Serializer::with_state(config, WriterState::default(), false)
650 }
651
652 pub fn with_headers<I, S>(config: SerializerConfig, names: I) -> Serializer
668 where
669 I: IntoIterator<Item = S>,
670 S: Into<String>,
671 {
672 let names = names.into_iter().map(Into::into).collect();
673 Serializer::with_state(config, WriterState::with_headers(names), false)
674 }
675
676 pub fn document(config: SerializerConfig) -> Serializer {
692 Serializer::with_state(config, WriterState::default(), true)
693 }
694
695 fn with_state(config: SerializerConfig, state: WriterState, document: bool) -> Serializer {
696 Serializer {
697 config,
698 state,
699 out: Vec::new(),
700 document,
701 in_progress: false,
702 }
703 }
704
705 pub fn config(&self) -> &SerializerConfig {
707 &self.config
708 }
709
710 pub fn headers(&self) -> Option<&[String]> {
715 self.state.names.as_deref()
716 }
717
718 pub fn serialize<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Error> {
723 ser::Serializer::serialize(self, value)
724 }
725
726 pub fn serialize_with<F, T: Serialize + ?Sized>(
731 &mut self,
732 value: &T,
733 setup: F,
734 ) -> Result<(), Error>
735 where
736 F: FnOnce(&mut SerializeDriver<'_>),
737 {
738 ser::Serializer::serialize_with(self, value, setup)
739 }
740
741 pub fn as_str(&self) -> &str {
743 unsafe { core::str::from_utf8_unchecked(&self.out) }
745 }
746
747 pub fn finish(self) -> String {
749 into_string(self.out)
750 }
751}
752
753impl ser::Serializer for Serializer {
754 fn drive(&mut self, driver: &mut SerializeDriver<'_>) -> Result<(), Error> {
755 if !self.config.context.is_empty() {
756 driver.set_default_context(self.config.context.clone());
757 }
758 if self.in_progress {
759 return Err(Error::in_progress());
760 }
761 let len = self.out.len();
762 match self
763 .config
764 .write_whole(&mut self.state, driver, self.document, &mut self.out)
765 {
766 Ok(()) => Ok(()),
767 Err(err) => {
768 self.out.truncate(len);
769 Err(err)
770 }
771 }
772 }
773}
774
775impl ser::StreamSerializer for Serializer {
776 fn output(&self) -> &[u8] {
777 &self.out
778 }
779
780 fn clear_output(&mut self) {
781 self.out.clear();
782 }
783
784 fn supports_partial(&self) -> bool {
786 self.document
787 }
788
789 fn drive_partial(
790 &mut self,
791 driver: &mut SerializeDriver<'_>,
792 limit: usize,
793 ) -> Result<bool, Error> {
794 if !self.config.context.is_empty() {
795 driver.set_default_context(self.config.context.clone());
796 }
797 if !self.document || (limit == usize::MAX && !self.in_progress) {
798 ser::Serializer::drive(self, driver)?;
799 return Ok(true);
800 }
801 let len = self.out.len();
802 match self
803 .config
804 .write(&mut self.state, driver, true, &mut self.out, limit)
805 {
806 Ok(done) => {
807 self.in_progress = !done;
808 Ok(done)
809 }
810 Err(err) => {
811 self.out.truncate(len);
814 Err(err)
815 }
816 }
817 }
818
819 fn in_progress(&self) -> bool {
820 self.in_progress
821 }
822}
823
824#[cfg(feature = "io")]
825impl SerializerConfig {
826 pub fn writer<W: std::io::Write>(&self, writer: W) -> deser_core::io::Writer<W, Serializer> {
848 deser_core::io::Writer::new(writer, Serializer::with_config(self.clone()))
849 }
850
851 pub fn to_writer<W: std::io::Write, T: Serialize + ?Sized>(
855 &self,
856 writer: W,
857 value: &T,
858 ) -> Result<(), Error> {
859 deser_core::io::to_writer(writer, Serializer::document(self.clone()), value)
860 }
861}
862
863#[cfg(feature = "io")]
876pub fn to_writer<W: std::io::Write, T: Serialize + ?Sized>(
877 writer: W,
878 value: &T,
879) -> Result<(), Error> {
880 SerializerConfig::new().to_writer(writer, value)
881}
882
883fn into_string(out: Vec<u8>) -> String {
888 debug_assert!(core::str::from_utf8(&out).is_ok());
889 unsafe { String::from_utf8_unchecked(out) }
891}
892
893pub fn to_string<T: Serialize + ?Sized>(value: &T) -> Result<String, Error> {
919 SerializerConfig::new().to_string(value)
920}
921
922#[derive(Clone, Default)]
924struct Record {
925 keys: Vec<u8>,
927 key_ends: Vec<usize>,
928 fields: Vec<u8>,
930 field_ends: Vec<usize>,
931}
932
933impl Record {
934 fn clear(&mut self) {
935 self.keys.clear();
936 self.key_ends.clear();
937 self.fields.clear();
938 self.field_ends.clear();
939 }
940
941 fn key(&self, index: usize) -> &[u8] {
942 let start = if index == 0 {
943 0
944 } else {
945 self.key_ends[index - 1]
946 };
947 &self.keys[start..self.key_ends[index]]
948 }
949
950 fn field(&self, index: usize) -> &[u8] {
951 let start = if index == 0 {
952 0
953 } else {
954 self.field_ends[index - 1]
955 };
956 &self.fields[start..self.field_ends[index]]
957 }
958}
959
960struct RecordWriter<'a> {
967 encoder: FieldEncoder<'a>,
968 names: Option<Vec<String>>,
969 len: Option<usize>,
970 document: bool,
971 direct: bool,
973 is_map: bool,
974 fields: usize,
976 record_start: usize,
978 field_ends: Vec<usize>,
981 record: Record,
983 scratch: Scratch,
985 open: bool,
987 limit: usize,
989 out: &'a mut Vec<u8>,
990}
991
992impl EventSink for RecordWriter<'_> {
993 #[inline]
994 fn event(
995 &mut self,
996 event: Event<'_>,
997 _value: SerializeRef<'_>,
998 state: &mut State,
999 ) -> Result<(), Error> {
1000 RecordWriter::event(self, event, state)
1001 }
1002
1003 #[inline]
1004 fn pause(&mut self) -> bool {
1005 !self.open && self.out.len() >= self.limit
1007 }
1008}
1009
1010impl RecordWriter<'_> {
1011 #[inline]
1012 fn event(&mut self, event: Event<'_>, state: &State) -> Result<(), Error> {
1013 if let Event::Atom(ref atom) = event
1015 && state.depth() == usize::from(self.document) + 1
1016 {
1017 return self.atom(atom, state.is_map_key());
1018 }
1019 self.structure(event, state)
1020 }
1021
1022 fn structure(&mut self, event: Event<'_>, state: &State) -> Result<(), Error> {
1024 let depth = match event {
1027 Event::MapStart(_) | Event::SeqStart(_) => state.depth().saturating_sub(1),
1028 _ => state.depth(),
1029 };
1030 let record_depth = usize::from(self.document);
1031 match event {
1032 Event::SeqStart(_) | Event::SeqEnd if self.document && depth == 0 => {}
1033 _ if depth < record_depth => {
1034 return Err(Error::new(
1035 ErrorKind::UnsupportedType,
1036 "CSV documents are sequences of records",
1037 ));
1038 }
1039 Event::MapStart(_) | Event::SeqStart(_) if depth == record_depth => {
1040 if self.names.is_none()
1041 && let Some(columns) = self.encoder.config.columns
1042 {
1043 let names: Vec<String> = columns.iter().map(|name| name.to_string()).collect();
1044 if self.encoder.config.headers {
1045 self.write_names(&names)?;
1046 }
1047 self.names = Some(names);
1048 }
1049 self.is_map = matches!(event, Event::MapStart(_));
1050 self.open = true;
1051 self.direct = !self.is_map || self.names.is_some();
1052 self.fields = 0;
1053 self.record_start = self.out.len();
1054 self.field_ends.clear();
1055 self.record.clear();
1056 }
1057 Event::MapEnd | Event::SeqEnd if depth == record_depth => {
1058 self.open = false;
1059 self.finish_record()?
1060 }
1061 _ if depth == record_depth => {
1062 return Err(Error::new(
1063 ErrorKind::UnsupportedType,
1064 "CSV records must be maps or sequences",
1065 ));
1066 }
1067 Event::MapStart(_) | Event::SeqStart(_) | Event::MapEnd | Event::SeqEnd => {
1069 return Err(Error::new(
1070 ErrorKind::UnsupportedType,
1071 "CSV fields cannot hold maps or sequences",
1072 ));
1073 }
1074 Event::Atom(ref atom) => return self.atom(atom, state.is_map_key()),
1075 }
1076 Ok(())
1077 }
1078
1079 #[inline(always)]
1081 fn atom(&mut self, atom: &Atom<'_>, is_key: bool) -> Result<(), Error> {
1082 if is_key {
1083 return self.key(atom);
1084 }
1085 let text = self.encoder.text(atom, &mut self.scratch)?;
1086 if self.direct {
1087 if self.fields > 0 {
1088 self.out.push(self.encoder.dialect.delimiter);
1089 }
1090 self.encoder.encode(text, self.out)?;
1091 self.field_ends.push(self.out.len());
1092 } else {
1093 self.encoder.encode(text, &mut self.record.fields)?;
1094 self.record.field_ends.push(self.record.fields.len());
1095 }
1096 self.fields += 1;
1097 Ok(())
1098 }
1099
1100 #[inline(always)]
1102 fn key(&mut self, atom: &Atom<'_>) -> Result<(), Error> {
1103 if self.direct
1105 && let Atom::Str(key) = atom
1106 && let Some(names) = &self.names
1107 && let Some(name) = names.get(self.fields)
1108 && same_key(name.as_bytes(), key.as_bytes())
1109 {
1110 return Ok(());
1111 }
1112 self.other_key(atom)
1113 }
1114
1115 #[inline(never)]
1117 fn other_key(&mut self, atom: &Atom<'_>) -> Result<(), Error> {
1118 let key = match atom {
1119 Atom::Null | Atom::Bytes(_) => None,
1120 atom => self.encoder.text(atom, &mut self.scratch)?,
1121 };
1122 let key = key.ok_or_else(unsupported_key)?;
1123 if !self.direct {
1124 self.record.keys.extend_from_slice(key.bytes);
1125 } else {
1126 let names = self.names.as_deref().unwrap_or_default();
1127 if let Some(name) = names.get(self.fields)
1128 && same_key(name.as_bytes(), key.bytes)
1129 {
1130 return Ok(());
1131 }
1132 let key = key.bytes.to_vec();
1133 self.collect();
1134 self.record.keys.extend_from_slice(&key);
1135 }
1136 self.record.key_ends.push(self.record.keys.len());
1137 Ok(())
1138 }
1139
1140 fn collect(&mut self) {
1142 let names = self.names.as_deref().unwrap_or_default();
1143 let mut start = self.record_start;
1144 for (index, &end) in self.field_ends.iter().enumerate() {
1145 if index > 0 {
1146 start += 1;
1148 }
1149 self.record.fields.extend_from_slice(&self.out[start..end]);
1150 self.record.field_ends.push(self.record.fields.len());
1151 self.record.keys.extend_from_slice(names[index].as_bytes());
1152 self.record.key_ends.push(self.record.keys.len());
1153 start = end;
1154 }
1155 self.out.truncate(self.record_start);
1156 self.direct = false;
1157 }
1158
1159 fn finish_record(&mut self) -> Result<(), Error> {
1161 let start = self.record_start;
1162 if !self.is_map {
1163 self.check_len(self.fields)?;
1164 return self.terminate(self.fields, start);
1165 }
1166
1167 if self.direct {
1168 let len = self.names.as_ref().map_or(0, Vec::len);
1170 for column in self.fields..len {
1171 if column > 0 {
1172 self.out.push(self.encoder.dialect.delimiter);
1173 }
1174 self.encoder.encode(None, self.out)?;
1175 }
1176 self.check_len(len)?;
1177 return self.terminate(len, start);
1178 }
1179
1180 let count = self.record.field_ends.len();
1181 if self.names.is_none() {
1182 let names: Vec<String> = (0..count)
1184 .map(|index| String::from_utf8_lossy(self.record.key(index)).into_owned())
1185 .collect();
1186 if self.encoder.config.headers {
1187 self.write_names(&names)?;
1188 }
1189 self.names = Some(names);
1190 }
1191 let len = self.names.as_ref().map_or(0, Vec::len);
1192 self.check_len(len)?;
1193 let names = self.names.as_ref().unwrap();
1194 let start = self.out.len();
1195 let mut order = vec![None; len];
1196 for index in 0..count {
1197 let key = String::from_utf8_lossy(self.record.key(index));
1198 match names.iter().position(|name| *name == key) {
1199 Some(column) if order[column].is_none() => order[column] = Some(index),
1200 Some(_) => {
1201 return Err(Error::new(
1202 ErrorKind::DuplicateKey,
1203 format!("duplicate field `{}`", key),
1204 ));
1205 }
1206 None => {
1207 return Err(Error::new(
1208 ErrorKind::UnknownField,
1209 format!("field `{}` is not a column", key),
1210 ));
1211 }
1212 }
1213 }
1214 for (column, index) in order.into_iter().enumerate() {
1215 if column > 0 {
1216 self.out.push(self.encoder.dialect.delimiter);
1217 }
1218 match index {
1219 Some(index) => self.out.extend_from_slice(self.record.field(index)),
1220 None => self.encoder.encode(None, self.out)?,
1222 }
1223 }
1224 self.terminate(len, start)
1225 }
1226
1227 fn check_len(&mut self, len: usize) -> Result<(), Error> {
1229 match self.len {
1230 Some(expected) if expected != len && !self.encoder.config.flexible => Err(Error::new(
1231 ErrorKind::WrongLength,
1232 format!("record has {} fields, expected {}", len, expected),
1233 )),
1234 Some(_) => Ok(()),
1235 None => {
1236 self.len = Some(len);
1237 Ok(())
1238 }
1239 }
1240 }
1241
1242 fn terminate(&mut self, len: usize, start: usize) -> Result<(), Error> {
1245 if len == 1 && self.out.len() == start {
1246 match self.encoder.dialect.quote {
1248 Some(quote) => self.out.extend_from_slice(&[quote, quote]),
1249 None => {
1250 return Err(Error::new(
1251 ErrorKind::InvalidValue,
1252 "a record with a single empty field needs quotes",
1253 ));
1254 }
1255 }
1256 }
1257 match self.encoder.config.terminator {
1258 Terminator::Newline => self.out.push(b'\n'),
1259 Terminator::CrLf => self.out.extend_from_slice(b"\r\n"),
1260 Terminator::Byte(byte) => self.out.push(byte),
1261 }
1262 Ok(())
1263 }
1264
1265 fn write_names(&mut self, names: &[String]) -> Result<(), Error> {
1267 let start = self.out.len();
1268 for (index, name) in names.iter().enumerate() {
1269 if index > 0 {
1270 self.out.push(self.encoder.dialect.delimiter);
1271 }
1272 let text = Text {
1273 bytes: name.as_bytes(),
1274 numeric: false,
1275 };
1276 self.encoder.encode(Some(text), self.out)?;
1277 }
1278 self.terminate(names.len(), start)
1279 }
1280}
1281
1282#[derive(Clone, Copy)]
1284struct Text<'a> {
1285 bytes: &'a [u8],
1286 numeric: bool,
1287}
1288
1289#[derive(Clone, Copy)]
1291struct FieldEncoder<'a> {
1292 config: &'a SerializerConfig,
1293 dialect: &'a Dialect,
1294 bytes: BytesFormat,
1296 plain: bool,
1300}
1301
1302impl FieldEncoder<'_> {
1303 #[inline(always)]
1305 fn encode(&self, text: Option<Text<'_>>, out: &mut Vec<u8>) -> Result<(), Error> {
1306 if self.plain
1308 && let Some(Text { bytes, .. }) = text
1309 && !self.dialect.has_special(bytes)
1310 {
1311 push_bytes(out, bytes);
1312 return Ok(());
1313 }
1314 self.encode_special(text, out)
1315 }
1316
1317 #[inline(never)]
1319 fn encode_special(&self, text: Option<Text<'_>>, out: &mut Vec<u8>) -> Result<(), Error> {
1320 let config = self.config;
1321 let Some(Text { bytes, numeric }) = text else {
1322 if let Nulls::Text(null) = config.nulls {
1323 out.extend_from_slice(null.as_bytes());
1324 }
1325 return Ok(());
1326 };
1327 let reads_as_null = match config.nulls {
1328 Nulls::None => false,
1329 Nulls::Empty => bytes.is_empty(),
1330 Nulls::Text(null) => bytes == null.as_bytes(),
1331 };
1332 let formula = config.escape_formulas
1335 && !numeric
1336 && matches!(
1337 bytes.first(),
1338 Some(b'=' | b'+' | b'-' | b'@' | b'\t' | b'\r')
1339 );
1340 let has_special = self.dialect.has_special(bytes);
1341 let quote_style = match config.quote_style {
1342 QuoteStyle::Always => true,
1343 QuoteStyle::NonNumeric => !numeric,
1344 QuoteStyle::Necessary | QuoteStyle::Never => false,
1345 };
1346 if !quote_style && !has_special && !reads_as_null && !formula {
1347 out.extend_from_slice(bytes);
1348 return Ok(());
1349 }
1350
1351 let prefix: &[u8] = if formula { b"'" } else { b"" };
1352 let escape = config.escape.byte();
1353 let prefix_is_special = formula && self.dialect.is_special(b'\'');
1354 let quoted = quote_style
1357 || (formula && self.dialect.quote.is_some() && config.quote_style != QuoteStyle::Never)
1358 || (escape.is_none() && (has_special || prefix_is_special || reads_as_null))
1359 || (reads_as_null && bytes.is_empty());
1360 let text = prefix.iter().chain(bytes).copied();
1361
1362 if !quoted {
1363 for (index, byte) in text.enumerate() {
1364 if self.dialect.is_special(byte) || (index == 0 && reads_as_null) {
1365 out.push(escape.unwrap_or(b'\\'));
1367 out.push(self.escaped(byte));
1368 } else {
1369 out.push(byte);
1370 }
1371 }
1372 return Ok(());
1373 }
1374
1375 let quote = match self.dialect.quote {
1376 Some(quote) if config.quote_style != QuoteStyle::Never => quote,
1377 _ => {
1378 return Err(Error::new(
1379 ErrorKind::InvalidValue,
1380 format!(
1381 "field {:?} needs to be quoted",
1382 String::from_utf8_lossy(bytes)
1383 ),
1384 ));
1385 }
1386 };
1387 out.push(quote);
1388 if formula {
1389 self.push_quoted(b'\'', quote, out)?;
1390 }
1391 let mut bytes = bytes;
1392 loop {
1393 let run = bytes
1395 .iter()
1396 .position(|&b| b == quote || Some(b) == escape)
1397 .unwrap_or(bytes.len());
1398 out.extend_from_slice(&bytes[..run]);
1399 let Some((&byte, rest)) = bytes[run..].split_first() else {
1400 break;
1401 };
1402 bytes = rest;
1403 self.push_quoted(byte, quote, out)?;
1404 }
1405 out.push(quote);
1406 Ok(())
1407 }
1408
1409 fn push_quoted(&self, byte: u8, quote: u8, out: &mut Vec<u8>) -> Result<(), Error> {
1411 let escape = self.config.escape.byte();
1412 if byte == quote && self.config.double_quote {
1413 out.extend_from_slice(&[quote, quote]);
1414 } else if byte == quote || Some(byte) == escape {
1415 match escape {
1416 Some(escape) => out.extend_from_slice(&[escape, self.escaped(byte)]),
1417 None => {
1418 return Err(Error::new(
1419 ErrorKind::InvalidValue,
1420 "quotes in quoted fields need to be doubled or escaped",
1421 ));
1422 }
1423 }
1424 } else {
1425 out.push(byte);
1426 }
1427 Ok(())
1428 }
1429
1430 fn escaped(&self, byte: u8) -> u8 {
1432 match (self.config.escape, byte) {
1433 (Escape::Backslash, b'\t') => b't',
1434 (Escape::Backslash, b'\n') => b'n',
1435 (Escape::Backslash, b'\r') => b'r',
1436 (_, byte) => byte,
1437 }
1438 }
1439
1440 #[inline(always)]
1444 fn text<'a>(
1445 &self,
1446 atom: &'a Atom<'_>,
1447 scratch: &'a mut Scratch,
1448 ) -> Result<Option<Text<'a>>, Error> {
1449 let (bytes, numeric) = match *atom {
1450 Atom::Str(ref value) | Atom::Lexical(ref value) => (value.as_bytes(), false),
1451 Atom::Null => return Ok(None),
1452 Atom::Bool(value) => (if value { &b"true"[..] } else { b"false" }, false),
1453 Atom::U64(value) => (scratch.int.format(value).as_bytes(), true),
1455 Atom::I64(value) => (scratch.int.format(value).as_bytes(), true),
1456 Atom::F64(value) => (scratch.float(value), true),
1457 Atom::F32(value) => (scratch.float(value), true),
1458 _ => return self.other_text(atom, &mut scratch.bytes),
1459 };
1460 Ok(Some(Text { bytes, numeric }))
1461 }
1462
1463 #[inline(never)]
1465 fn other_text<'a>(
1466 &self,
1467 atom: &'a Atom<'_>,
1468 scratch: &'a mut Vec<u8>,
1469 ) -> Result<Option<Text<'a>>, Error> {
1470 scratch.clear();
1471 let numeric = match *atom {
1472 Atom::Char(value) => {
1473 scratch.extend_from_slice(value.encode_utf8(&mut [0; 4]).as_bytes());
1474 false
1475 }
1476 Atom::Bytes(ref bytes) => {
1477 let format = bytes.fallback.copied().unwrap_or(self.bytes);
1478 let text = format
1479 .encode(bytes)
1480 .or_else(|| BytesFormat::BASE64.encode(bytes))
1481 .unwrap_or_default();
1482 scratch.extend_from_slice(text.as_bytes());
1483 false
1484 }
1485 Atom::Ext(ref ext) => {
1486 if let Some(number) = ext.downcast_value_ref::<Number>() {
1487 scratch.extend_from_slice(number.as_str().as_bytes());
1489 } else if let Some(value) = ext.downcast_ref::<u128>() {
1490 let _ = write!(ByteWriter(scratch), "{}", value);
1491 } else if let Some(value) = ext.downcast_ref::<i128>() {
1492 let _ = write!(ByteWriter(scratch), "{}", value);
1493 } else {
1494 return match ext.fallback() {
1495 Atom::Ext(_) => Err(Error::new(
1496 ErrorKind::UnsupportedType,
1497 format!("CSV does not support {}", ext.name()),
1498 )),
1499 fallback => {
1500 let mut inner = Scratch::new(Vec::new());
1501 let numeric = match self.text(&fallback, &mut inner)? {
1502 Some(text) => {
1503 let numeric = text.numeric;
1504 scratch.extend_from_slice(text.bytes);
1505 numeric
1506 }
1507 None => return Ok(None),
1508 };
1509 Ok(Some(Text {
1510 bytes: scratch,
1511 numeric,
1512 }))
1513 }
1514 };
1515 }
1516 true
1517 }
1518 Atom::Implicit(ref value) => {
1520 let mut inner = Scratch::new(Vec::new());
1521 return Ok(match self.text(&value.value().to_atom(), &mut inner)? {
1522 Some(text) => {
1523 let numeric = text.numeric;
1524 scratch.extend_from_slice(text.bytes);
1525 Some(Text {
1526 bytes: scratch,
1527 numeric,
1528 })
1529 }
1530 None => None,
1531 });
1532 }
1533 _ => {
1534 return Err(Error::new(
1535 ErrorKind::UnsupportedType,
1536 format!("CSV does not support {}", atom.name()),
1537 ));
1538 }
1539 };
1540 Ok(Some(Text {
1541 bytes: scratch,
1542 numeric,
1543 }))
1544 }
1545}
1546
1547struct ByteWriter<'a>(&'a mut Vec<u8>);
1549
1550impl fmt::Write for ByteWriter<'_> {
1551 fn write_str(&mut self, s: &str) -> fmt::Result {
1552 self.0.extend_from_slice(s.as_bytes());
1553 Ok(())
1554 }
1555}
1556
1557struct Scratch {
1559 bytes: Vec<u8>,
1561 int: itoa::Buffer,
1562 float: zmij::Buffer,
1563}
1564
1565impl Scratch {
1566 fn new(bytes: Vec<u8>) -> Scratch {
1567 Scratch {
1568 bytes,
1569 int: itoa::Buffer::new(),
1570 float: zmij::Buffer::new(),
1571 }
1572 }
1573
1574 #[inline]
1577 fn float<F: zmij::Float>(&mut self, value: F) -> &[u8] {
1578 self.float.format(value).as_bytes()
1580 }
1581}
1582
1583#[inline(always)]
1589fn push_bytes(out: &mut Vec<u8>, bytes: &[u8]) {
1590 let len = bytes.len();
1591 if len > 32 {
1592 out.extend_from_slice(bytes);
1593 return;
1594 }
1595 out.reserve(32);
1596 let start = out.len();
1597 unsafe {
1601 let dst = out.as_mut_ptr().add(start);
1602 match len {
1603 0 => {}
1604 1..=3 => {
1606 *dst = bytes[0];
1607 *dst.add(len / 2) = bytes[len / 2];
1608 *dst.add(len - 1) = bytes[len - 1];
1609 }
1610 4..=8 => {
1611 dst.cast::<u32>().write_unaligned(load_u32(bytes, 0));
1612 dst.add(len - 4)
1613 .cast::<u32>()
1614 .write_unaligned(load_u32(bytes, len - 4));
1615 }
1616 9..=16 => {
1617 dst.cast::<u64>().write_unaligned(load_u64(bytes, 0));
1618 dst.add(len - 8)
1619 .cast::<u64>()
1620 .write_unaligned(load_u64(bytes, len - 8));
1621 }
1622 _ => {
1623 dst.cast::<u128>().write_unaligned(load_u128(bytes, 0));
1624 dst.add(len - 16)
1625 .cast::<u128>()
1626 .write_unaligned(load_u128(bytes, len - 16));
1627 }
1628 }
1629 out.set_len(start + len);
1630 }
1631}
1632
1633#[inline(always)]
1638fn same_key(name: &[u8], key: &[u8]) -> bool {
1639 let len = name.len();
1640 if len != key.len() {
1641 return false;
1642 }
1643 match len {
1644 0 => true,
1645 1..=3 => {
1647 name[0] == key[0] && name[len / 2] == key[len / 2] && name[len - 1] == key[len - 1]
1648 }
1649 4..=8 => {
1650 load_u32(name, 0) == load_u32(key, 0)
1651 && load_u32(name, len - 4) == load_u32(key, len - 4)
1652 }
1653 9..=16 => {
1654 load_u64(name, 0) == load_u64(key, 0)
1655 && load_u64(name, len - 8) == load_u64(key, len - 8)
1656 }
1657 _ => name == key,
1658 }
1659}
1660
1661#[cold]
1662fn unsupported_key() -> Error {
1663 Error::new(
1664 ErrorKind::UnsupportedType,
1665 "the keys of records must be strings, numbers or booleans",
1666 )
1667}
1668
1669#[cfg(test)]
1670mod tests {
1671 use super::*;
1672
1673 #[test]
1674 fn test_push_bytes() {
1675 let text: Vec<u8> = (b'a'..=b'z').chain(b'A'..=b'Z').collect();
1676 for len in 0..=text.len() {
1677 for prefix in [0, 1, 7] {
1678 let mut out = vec![b'-'; prefix];
1679 push_bytes(&mut out, &text[..len]);
1680 assert_eq!(&out[prefix..], &text[..len]);
1681 assert_eq!(out.len(), prefix + len);
1682 }
1683 }
1684 }
1685
1686 #[test]
1687 fn test_same_key() {
1688 let text: Vec<u8> = (b'a'..=b'z').chain(b'A'..=b'Z').collect();
1689 for len in 0..=text.len() {
1690 let name = &text[..len];
1691 assert!(same_key(name, &text[..len]));
1692 if len > 0 {
1693 assert!(!same_key(name, &text[..len - 1]));
1694 assert!(!same_key(&text[..len - 1], name));
1695 }
1696 for pos in 0..len {
1697 let mut key = name.to_vec();
1698 key[pos] ^= 1;
1699 assert!(!same_key(name, &key), "{:?}", key);
1700 }
1701 }
1702 }
1703}