1use core::fmt;
2use core::str;
3
4use memchr::memchr;
5
6use crate::{QuoteStyle, Terminator};
7
8#[derive(Debug)]
13pub struct WriterBuilder {
14 wtr: Writer,
15}
16
17impl WriterBuilder {
18 pub fn new() -> WriterBuilder {
20 let wtr = Writer {
21 state: WriterState::default(),
22 requires_quotes: [false; 256],
23 delimiter: b',',
24 term: Terminator::Any(b'\n'),
25 style: QuoteStyle::default(),
26 quote: b'"',
27 escape: b'\\',
28 double_quote: true,
29 comment: None,
30 };
31 WriterBuilder { wtr: wtr }
32 }
33
34 pub fn build(&self) -> Writer {
36 use crate::Terminator::*;
37
38 let mut wtr = self.wtr.clone();
39 wtr.requires_quotes[self.wtr.delimiter as usize] = true;
40 wtr.requires_quotes[self.wtr.quote as usize] = true;
41 if !self.wtr.double_quote {
42 wtr.requires_quotes[self.wtr.escape as usize] = true;
45 }
46 match self.wtr.term {
47 CRLF | Any(b'\n') | Any(b'\r') => {
48 wtr.requires_quotes[b'\r' as usize] = true;
53 wtr.requires_quotes[b'\n' as usize] = true;
54 }
55 Any(b) => {
56 wtr.requires_quotes[b as usize] = true;
57 }
58 _ => unreachable!(),
59 }
60 if let Some(comment) = self.wtr.comment {
65 wtr.requires_quotes[comment as usize] = true;
66 }
67 wtr
68 }
69
70 pub fn delimiter(&mut self, delimiter: u8) -> &mut WriterBuilder {
74 self.wtr.delimiter = delimiter;
75 self
76 }
77
78 pub fn terminator(&mut self, term: Terminator) -> &mut WriterBuilder {
85 self.wtr.term = term;
86 self
87 }
88
89 pub fn quote_style(&mut self, style: QuoteStyle) -> &mut WriterBuilder {
97 self.wtr.style = style;
98 self
99 }
100
101 pub fn quote(&mut self, quote: u8) -> &mut WriterBuilder {
105 self.wtr.quote = quote;
106 self
107 }
108
109 pub fn escape(&mut self, escape: u8) -> &mut WriterBuilder {
115 self.wtr.escape = escape;
116 self
117 }
118
119 pub fn double_quote(&mut self, yes: bool) -> &mut WriterBuilder {
127 self.wtr.double_quote = yes;
128 self
129 }
130
131 pub fn comment(&mut self, comment: Option<u8>) -> &mut WriterBuilder {
138 self.wtr.comment = comment;
139 self
140 }
141}
142
143impl Default for WriterBuilder {
144 fn default() -> WriterBuilder {
145 WriterBuilder::new()
146 }
147}
148
149#[derive(Clone, Debug, Eq, PartialEq)]
156pub enum WriteResult {
157 InputEmpty,
160 OutputFull,
165}
166
167pub struct Writer {
180 state: WriterState,
181 requires_quotes: [bool; 256],
182 delimiter: u8,
183 term: Terminator,
184 style: QuoteStyle,
185 quote: u8,
186 escape: u8,
187 double_quote: bool,
188 comment: Option<u8>,
189}
190
191impl Clone for Writer {
192 fn clone(&self) -> Writer {
193 let mut requires_quotes = [false; 256];
194 for i in 0..256 {
195 requires_quotes[i] = self.requires_quotes[i];
196 }
197 Writer {
198 state: self.state.clone(),
199 requires_quotes: requires_quotes,
200 delimiter: self.delimiter,
201 term: self.term,
202 style: self.style,
203 quote: self.quote,
204 escape: self.escape,
205 double_quote: self.double_quote,
206 comment: self.comment,
207 }
208 }
209}
210
211impl fmt::Debug for Writer {
212 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
213 f.debug_struct("Writer")
214 .field("state", &self.state)
215 .field("delimiter", &self.delimiter)
216 .field("term", &self.term)
217 .field("style", &self.style)
218 .field("quote", &self.quote)
219 .field("escape", &self.escape)
220 .field("double_quote", &self.double_quote)
221 .finish()
222 }
223}
224
225#[derive(Clone, Debug)]
226struct WriterState {
227 in_field: bool,
231 quoting: bool,
235 record_bytes: u64,
240}
241
242impl Writer {
243 pub fn new() -> Writer {
245 Writer::default()
246 }
247
248 pub fn finish(&mut self, mut output: &mut [u8]) -> (WriteResult, usize) {
253 let mut nout = 0;
254 if self.state.record_bytes == 0 && self.state.in_field {
255 assert!(!self.state.quoting);
256 let (res, o) = self.write(&[self.quote, self.quote], output);
257 if o == 0 {
258 return (res, 0);
259 }
260 output = &mut moving(output)[o..];
261 nout += o;
262 self.state.record_bytes += o as u64;
263 }
264 if !self.state.quoting {
265 return (WriteResult::InputEmpty, nout);
266 }
267 let (res, o) = self.write(&[self.quote], output);
268 if o == 0 {
269 return (res, nout);
270 }
271 nout += o;
272 self.state.record_bytes = 0;
273 self.state.in_field = false;
274 self.state.quoting = false;
275 (res, nout)
276 }
277
278 pub fn field(
301 &mut self,
302 input: &[u8],
303 mut output: &mut [u8],
304 ) -> (WriteResult, usize, usize) {
305 let (mut nin, mut nout) = (0, 0);
306
307 if !self.state.in_field {
308 self.state.quoting = self.should_quote(input);
309 if self.state.quoting {
310 let (res, o) = self.write(&[self.quote], output);
311 if o == 0 {
312 return (res, 0, 0);
313 }
314 output = &mut moving(output)[o..];
315 nout += o;
316 self.state.record_bytes += o as u64;
317 }
318 self.state.in_field = true;
319 }
320 let (res, i, o) = if self.state.quoting {
321 quote(input, output, self.quote, self.escape, self.double_quote)
322 } else {
323 write_optimistic(input, output)
324 };
325 nin += i;
326 nout += o;
327 self.state.record_bytes += o as u64;
328 (res, nin, nout)
329 }
330
331 pub fn delimiter(
340 &mut self,
341 mut output: &mut [u8],
342 ) -> (WriteResult, usize) {
343 let mut nout = 0;
344 if self.state.quoting {
345 let (res, o) = self.write(&[self.quote], output);
346 if o == 0 {
347 return (res, o);
348 }
349 output = &mut moving(output)[o..];
350 nout += o;
351 self.state.record_bytes += o as u64;
352 self.state.quoting = false;
353 }
354 let (res, o) = self.write(&[self.delimiter], output);
355 if o == 0 {
356 return (res, nout);
357 }
358 nout += o;
359 self.state.record_bytes += o as u64;
360 self.state.in_field = false;
361 (res, nout)
362 }
363
364 pub fn terminator(
372 &mut self,
373 mut output: &mut [u8],
374 ) -> (WriteResult, usize) {
375 let mut nout = 0;
376 if self.state.record_bytes == 0 {
377 assert!(!self.state.quoting);
378 let (res, o) = self.write(&[self.quote, self.quote], output);
379 if o == 0 {
380 return (res, 0);
381 }
382 output = &mut moving(output)[o..];
383 nout += o;
384 self.state.record_bytes += o as u64;
385 }
386 if self.state.quoting {
387 let (res, o) = self.write(&[self.quote], output);
388 if o == 0 {
389 return (res, o);
390 }
391 output = &mut moving(output)[o..];
392 nout += o;
393 self.state.record_bytes += o as u64;
394 self.state.quoting = false;
395 }
396 let (res, o) = match self.term {
397 Terminator::CRLF => write_pessimistic(&[b'\r', b'\n'], output),
398 Terminator::Any(b) => write_pessimistic(&[b], output),
399 _ => unreachable!(),
400 };
401 if o == 0 {
402 return (res, nout);
403 }
404 nout += o;
405 self.state.record_bytes = 0;
406 self.state.in_field = false;
407 (res, nout)
408 }
409
410 #[inline]
414 fn needs_quotes(&self, mut input: &[u8]) -> bool {
415 let mut needs = false;
416 while !needs && input.len() >= 8 {
417 needs = self.requires_quotes[input[0] as usize]
418 || self.requires_quotes[input[1] as usize]
419 || self.requires_quotes[input[2] as usize]
420 || self.requires_quotes[input[3] as usize]
421 || self.requires_quotes[input[4] as usize]
422 || self.requires_quotes[input[5] as usize]
423 || self.requires_quotes[input[6] as usize]
424 || self.requires_quotes[input[7] as usize];
425 input = &input[8..];
426 }
427 needs || input.iter().any(|&b| self.is_special_byte(b))
428 }
429
430 #[inline]
436 pub fn is_special_byte(&self, b: u8) -> bool {
437 self.requires_quotes[b as usize]
438 }
439
440 #[inline]
443 pub fn should_quote(&self, input: &[u8]) -> bool {
444 match self.style {
445 QuoteStyle::Always => true,
446 QuoteStyle::Never => false,
447 QuoteStyle::NonNumeric => is_non_numeric(input),
448 QuoteStyle::Necessary => self.needs_quotes(input),
449 _ => unreachable!(),
450 }
451 }
452
453 #[inline]
455 pub fn get_delimiter(&self) -> u8 {
456 self.delimiter
457 }
458
459 #[inline]
461 pub fn get_terminator(&self) -> Terminator {
462 self.term
463 }
464
465 #[inline]
467 pub fn get_quote_style(&self) -> QuoteStyle {
468 self.style
469 }
470
471 #[inline]
473 pub fn get_quote(&self) -> u8 {
474 self.quote
475 }
476
477 #[inline]
479 pub fn get_escape(&self) -> u8 {
480 self.escape
481 }
482
483 #[inline]
486 pub fn get_double_quote(&self) -> bool {
487 self.double_quote
488 }
489
490 fn write(&self, data: &[u8], output: &mut [u8]) -> (WriteResult, usize) {
491 if data.len() > output.len() {
492 (WriteResult::OutputFull, 0)
493 } else {
494 output[..data.len()].copy_from_slice(data);
495 (WriteResult::InputEmpty, data.len())
496 }
497 }
498}
499
500impl Default for Writer {
501 fn default() -> Writer {
502 WriterBuilder::new().build()
503 }
504}
505
506impl Default for WriterState {
507 fn default() -> WriterState {
508 WriterState { in_field: false, quoting: false, record_bytes: 0 }
509 }
510}
511
512pub fn is_non_numeric(input: &[u8]) -> bool {
514 let s = match str::from_utf8(input) {
515 Err(_) => return true,
516 Ok(s) => s,
517 };
518 !s.parse::<f64>().is_ok() && !s.parse::<i128>().is_ok()
522}
523
524pub fn quote(
549 mut input: &[u8],
550 mut output: &mut [u8],
551 quote: u8,
552 escape: u8,
553 double_quote: bool,
554) -> (WriteResult, usize, usize) {
555 let (mut nin, mut nout) = (0, 0);
556 loop {
557 match memchr(quote, input) {
558 None => {
559 let (res, i, o) = write_optimistic(input, output);
560 nin += i;
561 nout += o;
562 return (res, nin, nout);
563 }
564 Some(next_quote) => {
565 let (res, i, o) =
566 write_optimistic(&input[..next_quote], output);
567 input = &input[i..];
568 output = &mut moving(output)[o..];
569 nin += i;
570 nout += o;
571 if let WriteResult::OutputFull = res {
572 return (res, nin, nout);
573 }
574 if double_quote {
575 let (res, o) = write_pessimistic(&[quote, quote], output);
576 if let WriteResult::OutputFull = res {
577 return (res, nin, nout);
578 }
579 nout += o;
580 output = &mut moving(output)[o..];
581 } else {
582 let (res, o) = write_pessimistic(&[escape, quote], output);
583 if let WriteResult::OutputFull = res {
584 return (res, nin, nout);
585 }
586 nout += o;
587 output = &mut moving(output)[o..];
588 }
589 nin += 1;
590 input = &input[1..];
591 }
592 }
593 }
594}
595
596fn write_optimistic(
608 input: &[u8],
609 output: &mut [u8],
610) -> (WriteResult, usize, usize) {
611 if input.len() > output.len() {
612 let input = &input[..output.len()];
613 output.copy_from_slice(input);
614 (WriteResult::OutputFull, output.len(), output.len())
615 } else {
616 output[..input.len()].copy_from_slice(input);
617 (WriteResult::InputEmpty, input.len(), input.len())
618 }
619}
620
621fn write_pessimistic(input: &[u8], output: &mut [u8]) -> (WriteResult, usize) {
627 if input.len() > output.len() {
628 (WriteResult::OutputFull, 0)
629 } else {
630 output[..input.len()].copy_from_slice(input);
631 (WriteResult::InputEmpty, input.len())
632 }
633}
634
635fn moving<T>(x: T) -> T {
638 x
639}
640
641#[cfg(test)]
642mod tests {
643 use crate::writer::WriteResult::*;
644 use crate::writer::{quote, QuoteStyle, Writer, WriterBuilder};
645
646 fn b(s: &str) -> &[u8] {
648 s.as_bytes()
649 }
650 fn s(b: &[u8]) -> &str {
651 ::core::str::from_utf8(b).unwrap()
652 }
653
654 macro_rules! assert_field {
655 (
656 $wtr:expr, $inp:expr, $out:expr,
657 $expect_in:expr, $expect_out:expr,
658 $expect_res:expr, $expect_data:expr
659 ) => {{
660 let (res, i, o) = $wtr.field($inp, $out);
661 assert_eq!($expect_res, res, "result");
662 assert_eq!($expect_in, i, "input");
663 assert_eq!($expect_out, o, "output");
664 assert_eq!($expect_data, s(&$out[..o]), "data");
665 }};
666 }
667
668 macro_rules! assert_write {
669 (
670 $wtr:expr, $which:ident, $out:expr,
671 $expect_out:expr, $expect_res:expr, $expect_data:expr
672 ) => {{
673 let (res, o) = $wtr.$which($out);
674 assert_eq!($expect_res, res, "result");
675 assert_eq!($expect_out, o, "output");
676 assert_eq!($expect_data, s(&$out[..o]), "data");
677 }};
678 }
679
680 #[test]
681 fn writer_one_field() {
682 let mut wtr = Writer::new();
683 let out = &mut [0; 1024];
684 let mut n = 0;
685
686 assert_field!(wtr, b("abc"), &mut out[n..], 3, 3, InputEmpty, "abc");
687 n += 3;
688
689 assert_write!(wtr, finish, &mut out[n..], 0, InputEmpty, "");
690 }
691
692 #[test]
693 fn writer_one_empty_field_terminator() {
694 let mut wtr = Writer::new();
695 let out = &mut [0; 1024];
696
697 assert_field!(wtr, b(""), &mut out[..], 0, 0, InputEmpty, "");
698 assert_write!(wtr, terminator, &mut out[..], 3, InputEmpty, "\"\"\n");
699 assert_write!(wtr, finish, &mut out[..], 0, InputEmpty, "");
700 }
701
702 #[test]
703 fn writer_one_empty_field_finish() {
704 let mut wtr = Writer::new();
705 let out = &mut [0; 1024];
706
707 assert_field!(wtr, b(""), &mut out[..], 0, 0, InputEmpty, "");
708 assert_write!(wtr, finish, &mut out[..], 2, InputEmpty, "\"\"");
709 }
710
711 #[test]
712 fn writer_many_one_empty_field_finish() {
713 let mut wtr = Writer::new();
714 let out = &mut [0; 1024];
715
716 assert_field!(wtr, b(""), &mut out[..], 0, 0, InputEmpty, "");
717 assert_write!(wtr, terminator, &mut out[..], 3, InputEmpty, "\"\"\n");
718 assert_field!(wtr, b(""), &mut out[..], 0, 0, InputEmpty, "");
719 assert_write!(wtr, finish, &mut out[..], 2, InputEmpty, "\"\"");
720 }
721
722 #[test]
723 fn writer_many_one_empty_field_terminator() {
724 let mut wtr = Writer::new();
725 let out = &mut [0; 1024];
726
727 assert_field!(wtr, b(""), &mut out[..], 0, 0, InputEmpty, "");
728 assert_write!(wtr, terminator, &mut out[..], 3, InputEmpty, "\"\"\n");
729 assert_field!(wtr, b(""), &mut out[..], 0, 0, InputEmpty, "");
730 assert_write!(wtr, terminator, &mut out[..], 3, InputEmpty, "\"\"\n");
731 assert_write!(wtr, finish, &mut out[..], 0, InputEmpty, "");
732 }
733
734 #[test]
735 fn writer_one_field_quote() {
736 let mut wtr = Writer::new();
737 let out = &mut [0; 1024];
738 let mut n = 0;
739
740 assert_field!(
741 wtr,
742 b("a\"bc"),
743 &mut out[n..],
744 4,
745 6,
746 InputEmpty,
747 "\"a\"\"bc"
748 );
749 n += 6;
750
751 assert_write!(wtr, finish, &mut out[n..], 1, InputEmpty, "\"");
752 }
753
754 #[test]
755 fn writer_one_field_stream() {
756 let mut wtr = Writer::new();
757 let out = &mut [0; 1024];
758 let mut n = 0;
759
760 assert_field!(wtr, b("abc"), &mut out[n..], 3, 3, InputEmpty, "abc");
761 n += 3;
762 assert_field!(wtr, b("x"), &mut out[n..], 1, 1, InputEmpty, "x");
763 n += 1;
764
765 assert_write!(wtr, finish, &mut out[n..], 0, InputEmpty, "");
766 }
767
768 #[test]
769 fn writer_one_field_stream_quote() {
770 let mut wtr = Writer::new();
771 let out = &mut [0; 1024];
772 let mut n = 0;
773
774 assert_field!(
775 wtr,
776 b("abc\""),
777 &mut out[n..],
778 4,
779 6,
780 InputEmpty,
781 "\"abc\"\""
782 );
783 n += 6;
784 assert_field!(wtr, b("x"), &mut out[n..], 1, 1, InputEmpty, "x");
785 n += 1;
786
787 assert_write!(wtr, finish, &mut out[n..], 1, InputEmpty, "\"");
788 }
789
790 #[test]
791 fn writer_one_field_stream_quote_partial() {
792 let mut wtr = Writer::new();
793 let out = &mut [0; 4];
794
795 assert_field!(wtr, b("ab\"xyz"), out, 2, 3, OutputFull, "\"ab");
796 assert_field!(wtr, b("\"xyz"), out, 3, 4, OutputFull, "\"\"xy");
797 assert_field!(wtr, b("z"), out, 1, 1, InputEmpty, "z");
798 assert_write!(wtr, finish, out, 1, InputEmpty, "\"");
799 }
800
801 #[test]
802 fn writer_two_fields() {
803 let mut wtr = Writer::new();
804 let out = &mut [0; 1024];
805 let mut n = 0;
806
807 assert_field!(wtr, b("abc"), &mut out[n..], 3, 3, InputEmpty, "abc");
808 n += 3;
809 assert_write!(wtr, delimiter, &mut out[n..], 1, InputEmpty, ",");
810 n += 1;
811 assert_field!(wtr, b("yz"), &mut out[n..], 2, 2, InputEmpty, "yz");
812 n += 2;
813
814 assert_write!(wtr, finish, &mut out[n..], 0, InputEmpty, "");
815
816 assert_eq!("abc,yz", s(&out[..n]));
817 }
818
819 #[test]
820 fn writer_two_fields_non_numeric() {
821 let mut wtr =
822 WriterBuilder::new().quote_style(QuoteStyle::NonNumeric).build();
823 let out = &mut [0; 1024];
824 let mut n = 0;
825
826 assert_field!(wtr, b("abc"), &mut out[n..], 3, 4, InputEmpty, "\"abc");
827 n += 4;
828 assert_write!(wtr, delimiter, &mut out[n..], 2, InputEmpty, "\",");
829 n += 2;
830 assert_field!(wtr, b("5.2"), &mut out[n..], 3, 3, InputEmpty, "5.2");
831 n += 3;
832 assert_write!(wtr, delimiter, &mut out[n..], 1, InputEmpty, ",");
833 n += 1;
834 assert_field!(wtr, b("98"), &mut out[n..], 2, 2, InputEmpty, "98");
835 n += 2;
836
837 assert_write!(wtr, finish, &mut out[n..], 0, InputEmpty, "");
838
839 assert_eq!("\"abc\",5.2,98", s(&out[..n]));
840 }
841
842 #[test]
843 fn writer_two_fields_quote() {
844 let mut wtr = Writer::new();
845 let out = &mut [0; 1024];
846 let mut n = 0;
847
848 assert_field!(
849 wtr,
850 b("a,bc"),
851 &mut out[n..],
852 4,
853 5,
854 InputEmpty,
855 "\"a,bc"
856 );
857 n += 5;
858 assert_write!(wtr, delimiter, &mut out[n..], 2, InputEmpty, "\",");
859 n += 2;
860 assert_field!(wtr, b("\nz"), &mut out[n..], 2, 3, InputEmpty, "\"\nz");
861 n += 3;
862
863 assert_write!(wtr, finish, &mut out[n..], 1, InputEmpty, "\"");
864 n += 1;
865
866 assert_eq!("\"a,bc\",\"\nz\"", s(&out[..n]));
867 }
868
869 #[test]
870 fn writer_two_fields_two_records() {
871 let mut wtr = Writer::new();
872 let out = &mut [0; 1024];
873 let mut n = 0;
874
875 assert_field!(wtr, b("abc"), &mut out[n..], 3, 3, InputEmpty, "abc");
876 n += 3;
877 assert_write!(wtr, delimiter, &mut out[n..], 1, InputEmpty, ",");
878 n += 1;
879 assert_field!(wtr, b("yz"), &mut out[n..], 2, 2, InputEmpty, "yz");
880 n += 2;
881 assert_write!(wtr, terminator, &mut out[n..], 1, InputEmpty, "\n");
882 n += 1;
883 assert_field!(wtr, b("foo"), &mut out[n..], 3, 3, InputEmpty, "foo");
884 n += 3;
885 assert_write!(wtr, delimiter, &mut out[n..], 1, InputEmpty, ",");
886 n += 1;
887 assert_field!(wtr, b("quux"), &mut out[n..], 4, 4, InputEmpty, "quux");
888 n += 4;
889
890 assert_write!(wtr, finish, &mut out[n..], 0, InputEmpty, "");
891
892 assert_eq!("abc,yz\nfoo,quux", s(&out[..n]));
893 }
894
895 #[test]
896 fn writer_two_fields_two_records_quote() {
897 let mut wtr = Writer::new();
898 let out = &mut [0; 1024];
899 let mut n = 0;
900
901 assert_field!(
902 wtr,
903 b("a,bc"),
904 &mut out[n..],
905 4,
906 5,
907 InputEmpty,
908 "\"a,bc"
909 );
910 n += 5;
911 assert_write!(wtr, delimiter, &mut out[n..], 2, InputEmpty, "\",");
912 n += 2;
913 assert_field!(wtr, b("\nz"), &mut out[n..], 2, 3, InputEmpty, "\"\nz");
914 n += 3;
915 assert_write!(wtr, terminator, &mut out[n..], 2, InputEmpty, "\"\n");
916 n += 2;
917 assert_field!(
918 wtr,
919 b("f\"oo"),
920 &mut out[n..],
921 4,
922 6,
923 InputEmpty,
924 "\"f\"\"oo"
925 );
926 n += 6;
927 assert_write!(wtr, delimiter, &mut out[n..], 2, InputEmpty, "\",");
928 n += 2;
929 assert_field!(
930 wtr,
931 b("quux,"),
932 &mut out[n..],
933 5,
934 6,
935 InputEmpty,
936 "\"quux,"
937 );
938 n += 6;
939
940 assert_write!(wtr, finish, &mut out[n..], 1, InputEmpty, "\"");
941 n += 1;
942
943 assert_eq!("\"a,bc\",\"\nz\"\n\"f\"\"oo\",\"quux,\"", s(&out[..n]));
944 }
945
946 macro_rules! assert_quote {
947 (
948 $inp:expr, $out:expr,
949 $expect_in:expr, $expect_out:expr,
950 $expect_res:expr, $expect_data:expr
951 ) => {
952 assert_quote!(
953 $inp,
954 $out,
955 $expect_in,
956 $expect_out,
957 $expect_res,
958 $expect_data,
959 true
960 );
961 };
962 (
963 $inp:expr, $out:expr,
964 $expect_in:expr, $expect_out:expr,
965 $expect_res:expr, $expect_data:expr,
966 $double_quote:expr
967 ) => {{
968 let (res, i, o) = quote($inp, $out, b'"', b'\\', $double_quote);
969 assert_eq!($expect_res, res, "result");
970 assert_eq!($expect_in, i, "input");
971 assert_eq!($expect_out, o, "output");
972 assert_eq!(b($expect_data), &$out[..o], "data");
973 }};
974 }
975
976 #[test]
977 fn quote_empty() {
978 let inp = b("");
979 let out = &mut [0; 1024];
980
981 assert_quote!(inp, out, 0, 0, InputEmpty, "");
982 }
983
984 #[test]
985 fn quote_no_quotes() {
986 let inp = b("foobar");
987 let out = &mut [0; 1024];
988
989 assert_quote!(inp, out, 6, 6, InputEmpty, "foobar");
990 }
991
992 #[test]
993 fn quote_one_quote() {
994 let inp = b("\"");
995 let out = &mut [0; 1024];
996
997 assert_quote!(inp, out, 1, 2, InputEmpty, r#""""#);
998 }
999
1000 #[test]
1001 fn quote_two_quotes() {
1002 let inp = b("\"\"");
1003 let out = &mut [0; 1024];
1004
1005 assert_quote!(inp, out, 2, 4, InputEmpty, r#""""""#);
1006 }
1007
1008 #[test]
1009 fn quote_escaped_one() {
1010 let inp = b("\"");
1011 let out = &mut [0; 1024];
1012
1013 assert_quote!(inp, out, 1, 2, InputEmpty, r#"\""#, false);
1014 }
1015
1016 #[test]
1017 fn quote_escaped_two() {
1018 let inp = b("\"\"");
1019 let out = &mut [0; 1024];
1020
1021 assert_quote!(inp, out, 2, 4, InputEmpty, r#"\"\""#, false);
1022 }
1023
1024 #[test]
1025 fn quote_misc() {
1026 let inp = b(r#"foo "bar" baz "quux"?"#);
1027 let out = &mut [0; 1024];
1028
1029 assert_quote!(
1030 inp,
1031 out,
1032 21,
1033 25,
1034 InputEmpty,
1035 r#"foo ""bar"" baz ""quux""?"#
1036 );
1037 }
1038
1039 #[test]
1040 fn quote_stream_no_quotes() {
1041 let mut inp = b("fooba");
1042 let out = &mut [0; 2];
1043
1044 assert_quote!(inp, out, 2, 2, OutputFull, "fo");
1045 inp = &inp[2..];
1046 assert_quote!(inp, out, 2, 2, OutputFull, "ob");
1047 inp = &inp[2..];
1048 assert_quote!(inp, out, 1, 1, InputEmpty, "a");
1049 }
1050
1051 #[test]
1052 fn quote_stream_quotes() {
1053 let mut inp = b(r#"a"bc"d""#);
1054 let out = &mut [0; 2];
1055
1056 assert_quote!(inp, out, 1, 1, OutputFull, "a");
1057 inp = &inp[1..];
1058 assert_quote!(inp, out, 1, 2, OutputFull, r#""""#);
1059 inp = &inp[1..];
1060 assert_quote!(inp, out, 2, 2, OutputFull, "bc");
1061 inp = &inp[2..];
1062 assert_quote!(inp, out, 1, 2, OutputFull, r#""""#);
1063 inp = &inp[1..];
1064 assert_quote!(inp, out, 1, 1, OutputFull, "d");
1065 inp = &inp[1..];
1066 assert_quote!(inp, out, 1, 2, InputEmpty, r#""""#);
1067 }
1068
1069 #[test]
1070 fn comment_char_is_automatically_quoted() {
1071 let mut wtr = WriterBuilder::new().comment(Some(b'#')).build();
1072 let out = &mut [0; 1024];
1073
1074 assert_field!(
1075 wtr,
1076 b("# abc"),
1077 &mut out[..],
1078 5,
1079 6,
1080 InputEmpty,
1081 "\"# abc"
1082 );
1083 assert_write!(wtr, finish, &mut out[..], 1, InputEmpty, "\"");
1084 }
1085}