1use core::fmt;
2
3use crate::Terminator;
4
5#[derive(Clone, Debug)]
96pub struct Reader {
97 dfa: Dfa,
99 dfa_state: DfaState,
101 nfa_state: NfaState,
103 delimiter: u8,
105 term: Terminator,
107 quote: u8,
109 escape: Option<u8>,
111 double_quote: bool,
113 comment: Option<u8>,
115 quoting: bool,
118 use_nfa: bool,
123 line: u64,
125 has_read: bool,
127 output_pos: usize,
129}
130
131impl Default for Reader {
132 fn default() -> Reader {
133 Reader {
134 dfa: Dfa::new(),
135 dfa_state: DfaState::start(),
136 nfa_state: NfaState::StartRecord,
137 delimiter: b',',
138 term: Terminator::default(),
139 quote: b'"',
140 escape: None,
141 double_quote: true,
142 comment: None,
143 quoting: true,
144 use_nfa: false,
145 line: 1,
146 has_read: false,
147 output_pos: 0,
148 }
149 }
150}
151
152#[derive(Debug, Default)]
158pub struct ReaderBuilder {
159 rdr: Reader,
160}
161
162impl ReaderBuilder {
163 pub fn new() -> ReaderBuilder {
165 ReaderBuilder::default()
166 }
167
168 pub fn build(&self) -> Reader {
170 let mut rdr = self.rdr.clone();
171 rdr.build_dfa();
172 rdr
173 }
174
175 pub fn delimiter(&mut self, delimiter: u8) -> &mut ReaderBuilder {
179 self.rdr.delimiter = delimiter;
180 self
181 }
182
183 pub fn terminator(&mut self, term: Terminator) -> &mut ReaderBuilder {
189 self.rdr.term = term;
190 self
191 }
192
193 pub fn quote(&mut self, quote: u8) -> &mut ReaderBuilder {
197 self.rdr.quote = quote;
198 self
199 }
200
201 pub fn escape(&mut self, escape: Option<u8>) -> &mut ReaderBuilder {
208 self.rdr.escape = escape;
209 self
210 }
211
212 pub fn double_quote(&mut self, yes: bool) -> &mut ReaderBuilder {
217 self.rdr.double_quote = yes;
218 self
219 }
220
221 pub fn quoting(&mut self, yes: bool) -> &mut ReaderBuilder {
226 self.rdr.quoting = yes;
227 self
228 }
229
230 pub fn comment(&mut self, comment: Option<u8>) -> &mut ReaderBuilder {
237 self.rdr.comment = comment;
238 self
239 }
240
241 pub fn ascii(&mut self) -> &mut ReaderBuilder {
247 self.delimiter(b'\x1F').terminator(Terminator::Any(b'\x1E'))
248 }
249
250 #[doc(hidden)]
255 pub fn nfa(&mut self, yes: bool) -> &mut ReaderBuilder {
256 self.rdr.use_nfa = yes;
257 self
258 }
259}
260
261#[derive(Clone, Debug, Eq, PartialEq)]
263pub enum ReadFieldResult {
264 InputEmpty,
267 OutputFull,
270 Field {
275 record_end: bool,
277 },
278 End,
283}
284
285impl ReadFieldResult {
286 fn from_nfa(
287 state: NfaState,
288 inpdone: bool,
289 outdone: bool,
290 ) -> ReadFieldResult {
291 match state {
292 NfaState::End => ReadFieldResult::End,
293 NfaState::EndRecord | NfaState::CRLF => {
294 ReadFieldResult::Field { record_end: true }
295 }
296 NfaState::EndFieldDelim => {
297 ReadFieldResult::Field { record_end: false }
298 }
299 _ => {
300 assert!(!state.is_field_final());
301 if !inpdone && outdone {
302 ReadFieldResult::OutputFull
303 } else {
304 ReadFieldResult::InputEmpty
305 }
306 }
307 }
308 }
309}
310
311#[derive(Clone, Debug, Eq, PartialEq)]
314pub enum ReadFieldNoCopyResult {
315 InputEmpty,
318 Field {
323 record_end: bool,
325 },
326 End,
331}
332
333#[derive(Clone, Debug, Eq, PartialEq)]
335pub enum ReadRecordResult {
336 InputEmpty,
339 OutputFull,
342 OutputEndsFull,
345 Record,
347 End,
352}
353
354impl ReadRecordResult {
355 fn is_record(&self) -> bool {
356 *self == ReadRecordResult::Record
357 }
358
359 fn from_nfa(
360 state: NfaState,
361 inpdone: bool,
362 outdone: bool,
363 endsdone: bool,
364 ) -> ReadRecordResult {
365 match state {
366 NfaState::End => ReadRecordResult::End,
367 NfaState::EndRecord | NfaState::CRLF => ReadRecordResult::Record,
368 _ => {
369 assert!(!state.is_record_final());
370 if !inpdone && outdone {
371 ReadRecordResult::OutputFull
372 } else if !inpdone && endsdone {
373 ReadRecordResult::OutputEndsFull
374 } else {
375 ReadRecordResult::InputEmpty
376 }
377 }
378 }
379 }
380}
381
382#[derive(Clone, Debug, Eq, PartialEq)]
385pub enum ReadRecordNoCopyResult {
386 InputEmpty,
389 Record,
391 End,
396}
397
398#[derive(Clone, Debug, Eq, PartialEq)]
400enum NfaInputAction {
401 Epsilon,
403 CopyToOutput,
405 Discard,
409}
410
411#[derive(Copy, Clone, Debug, Eq, PartialEq)]
417enum NfaState {
418 EndFieldTerm = 200,
421 InRecordTerm = 201,
422 End = 202,
423
424 StartRecord = 0,
426 StartField = 1,
427 InField = 2,
428 InQuotedField = 3,
429 InEscapedQuote = 4,
430 InDoubleEscapedQuote = 5,
431 InComment = 6,
432 EndFieldDelim = 7,
435 EndRecord = 8,
438 CRLF = 9,
439}
440
441const NFA_STATES: &'static [NfaState] = &[
443 NfaState::StartRecord,
444 NfaState::StartField,
445 NfaState::EndFieldDelim,
446 NfaState::InField,
447 NfaState::InQuotedField,
448 NfaState::InEscapedQuote,
449 NfaState::InDoubleEscapedQuote,
450 NfaState::InComment,
451 NfaState::EndRecord,
452 NfaState::CRLF,
453];
454
455impl NfaState {
456 fn is_field_final(&self) -> bool {
458 match *self {
459 NfaState::End
460 | NfaState::EndRecord
461 | NfaState::CRLF
462 | NfaState::EndFieldDelim => true,
463 _ => false,
464 }
465 }
466
467 fn is_record_final(&self) -> bool {
469 match *self {
470 NfaState::End | NfaState::EndRecord | NfaState::CRLF => true,
471 _ => false,
472 }
473 }
474}
475
476impl Reader {
477 pub fn new() -> Reader {
479 ReaderBuilder::new().build()
480 }
481
482 pub fn reset(&mut self) {
486 self.dfa_state = self.dfa.new_state(NfaState::StartRecord);
487 self.nfa_state = NfaState::StartRecord;
488 self.line = 1;
489 self.has_read = false;
490 self.output_pos = 0;
491 }
492
493 pub fn line(&self) -> u64 {
498 self.line
499 }
500
501 pub fn set_line(&mut self, line: u64) {
506 self.line = line;
507 }
508
509 pub fn read_field(
539 &mut self,
540 input: &[u8],
541 output: &mut [u8],
542 ) -> (ReadFieldResult, usize, usize) {
543 let (input, bom_nin) = self.strip_utf8_bom(input);
544 let (res, nin, nout) = if self.use_nfa {
545 self.read_field_nfa(input, output)
546 } else {
547 self.read_field_dfa(input, output)
548 };
549 self.has_read = true;
550 (res, nin + bom_nin, nout)
551 }
552
553 pub fn read_record(
595 &mut self,
596 input: &[u8],
597 output: &mut [u8],
598 ends: &mut [usize],
599 ) -> (ReadRecordResult, usize, usize, usize) {
600 let (input, bom_nin) = self.strip_utf8_bom(input);
601 let (res, nin, nout, nend) = if self.use_nfa {
602 self.read_record_nfa(input, output, ends)
603 } else {
604 self.read_record_dfa(input, output, ends)
605 };
606 self.has_read = true;
607 (res, nin + bom_nin, nout, nend)
608 }
609
610 fn strip_utf8_bom<'a>(&self, input: &'a [u8]) -> (&'a [u8], usize) {
614 let (input, nin) = if {
615 !self.has_read
616 && input.len() >= 3
617 && &input[0..3] == b"\xef\xbb\xbf"
618 } {
619 (&input[3..], 3)
620 } else {
621 (input, 0)
622 };
623 (input, nin)
624 }
625
626 #[inline(always)]
627 fn read_record_dfa(
628 &mut self,
629 input: &[u8],
630 output: &mut [u8],
631 ends: &mut [usize],
632 ) -> (ReadRecordResult, usize, usize, usize) {
633 if input.is_empty() {
634 let s = self.transition_final_dfa(self.dfa_state);
635 let res =
636 self.dfa.new_read_record_result(s, true, false, false, false);
637 return match res {
645 ReadRecordResult::Record => {
646 if ends.is_empty() {
647 return (ReadRecordResult::OutputEndsFull, 0, 0, 0);
648 }
649 self.dfa_state = s;
650 ends[0] = self.output_pos;
651 self.output_pos = 0;
652 (res, 0, 0, 1)
653 }
654 _ => {
655 self.dfa_state = s;
656 (res, 0, 0, 0)
657 }
658 };
659 }
660 if output.is_empty() {
661 return (ReadRecordResult::OutputFull, 0, 0, 0);
662 }
663 if ends.is_empty() {
664 return (ReadRecordResult::OutputEndsFull, 0, 0, 0);
665 }
666 let (mut nin, mut nout, mut nend) = (0, 0, 0);
667 let mut state = self.dfa_state;
668 while nin < input.len() && nout < output.len() && nend < ends.len() {
669 let (s, has_out) = self.dfa.get_output(state, input[nin]);
670 self.line += (input[nin] == b'\n') as u64;
671 state = s;
672 if has_out {
673 output[nout] = input[nin];
674 nout += 1;
675 }
676 nin += 1;
677 if state >= self.dfa.final_field {
678 ends[nend] = self.output_pos + nout;
679 nend += 1;
680 if state > self.dfa.final_field {
681 break;
682 }
683 }
684 if state == self.dfa.in_field || state == self.dfa.in_quoted {
685 self.dfa
686 .classes
687 .scan_and_copy(input, &mut nin, output, &mut nout);
688 }
689 }
690 let res = self.dfa.new_read_record_result(
691 state,
692 false,
693 nin >= input.len(),
694 nout >= output.len(),
695 nend >= ends.len(),
696 );
697 self.dfa_state = state;
698 if res.is_record() {
699 self.output_pos = 0;
700 } else {
701 self.output_pos += nout;
702 }
703 (res, nin, nout, nend)
704 }
705
706 #[inline(always)]
707 fn read_field_dfa(
708 &mut self,
709 input: &[u8],
710 output: &mut [u8],
711 ) -> (ReadFieldResult, usize, usize) {
712 if input.is_empty() {
713 self.dfa_state = self.transition_final_dfa(self.dfa_state);
714 let res = self.dfa.new_read_field_result(
715 self.dfa_state,
716 true,
717 false,
718 false,
719 );
720 return (res, 0, 0);
721 }
722 if output.is_empty() {
723 return (ReadFieldResult::OutputFull, 0, 0);
724 }
725 let (mut nin, mut nout) = (0, 0);
726 let mut state = self.dfa_state;
727 while nin < input.len() && nout < output.len() {
728 let b = input[nin];
729 self.line += (b == b'\n') as u64;
730 let (s, has_out) = self.dfa.get_output(state, b);
731 state = s;
732 if has_out {
733 output[nout] = b;
734 nout += 1;
735 }
736 nin += 1;
737 if state >= self.dfa.final_field {
738 break;
739 }
740 }
741 let res = self.dfa.new_read_field_result(
742 state,
743 false,
744 nin >= input.len(),
745 nout >= output.len(),
746 );
747 self.dfa_state = state;
748 (res, nin, nout)
749 }
750
751 fn transition_final_dfa(&self, state: DfaState) -> DfaState {
754 if state >= self.dfa.final_record || state.is_start() {
759 self.dfa.new_state_final_end()
760 } else {
761 self.dfa.new_state_final_record()
762 }
763 }
764
765 fn build_dfa(&mut self) {
768 self.dfa.classes.add(self.delimiter);
807 if self.quoting {
808 self.dfa.classes.add(self.quote);
809 if let Some(escape) = self.escape {
810 self.dfa.classes.add(escape);
811 }
812 }
813 if let Some(comment) = self.comment {
814 self.dfa.classes.add(comment);
815 }
816 match self.term {
817 Terminator::Any(b) => self.dfa.classes.add(b),
818 Terminator::CRLF => {
819 self.dfa.classes.add(b'\r');
820 self.dfa.classes.add(b'\n');
821 }
822 _ => unreachable!(),
823 }
824 for &state in NFA_STATES {
827 for c in (0..256).map(|c| c as u8) {
828 let mut nfa_result = (state, NfaInputAction::Epsilon);
829 while nfa_result.0 != NfaState::End
831 && nfa_result.1 == NfaInputAction::Epsilon
832 {
833 nfa_result = self.transition_nfa(nfa_result.0, c);
834 }
835 let from = self.dfa.new_state(state);
836 let to = self.dfa.new_state(nfa_result.0);
837 self.dfa.set(
838 from,
839 c,
840 to,
841 nfa_result.1 == NfaInputAction::CopyToOutput,
842 );
843 }
844 }
845 self.dfa_state = self.dfa.new_state(NfaState::StartRecord);
846 self.dfa.finish();
847 }
848
849 #[inline(always)]
855 fn read_record_nfa(
856 &mut self,
857 input: &[u8],
858 output: &mut [u8],
859 ends: &mut [usize],
860 ) -> (ReadRecordResult, usize, usize, usize) {
861 if input.is_empty() {
862 let s = self.transition_final_nfa(self.nfa_state);
863 let res = ReadRecordResult::from_nfa(s, false, false, false);
864 return match res {
865 ReadRecordResult::Record => {
866 if ends.is_empty() {
867 return (ReadRecordResult::OutputEndsFull, 0, 0, 0);
868 }
869 self.nfa_state = s;
870 ends[0] = self.output_pos;
871 self.output_pos = 0;
872 (res, 0, 0, 1)
873 }
874 _ => {
875 self.nfa_state = s;
876 (res, 0, 0, 0)
877 }
878 };
879 }
880 if output.is_empty() {
881 return (ReadRecordResult::OutputFull, 0, 0, 0);
882 }
883 if ends.is_empty() {
884 return (ReadRecordResult::OutputEndsFull, 0, 0, 0);
885 }
886 let (mut nin, mut nout, mut nend) = (0, self.output_pos, 0);
887 let mut state = self.nfa_state;
888 while nin < input.len() && nout < output.len() && nend < ends.len() {
889 let (s, io) = self.transition_nfa(state, input[nin]);
890 match io {
891 NfaInputAction::CopyToOutput => {
892 output[nout] = input[nin];
893 nout += 1;
894 nin += 1;
895 }
896 NfaInputAction::Discard => {
897 nin += 1;
898 }
899 NfaInputAction::Epsilon => {}
900 }
901 state = s;
902 if state.is_field_final() {
903 ends[nend] = nout;
904 nend += 1;
905 if state != NfaState::EndFieldDelim {
906 break;
907 }
908 }
909 }
910 let res = ReadRecordResult::from_nfa(
911 state,
912 nin >= input.len(),
913 nout >= output.len(),
914 nend >= ends.len(),
915 );
916 self.nfa_state = state;
917 self.output_pos = if res.is_record() { 0 } else { nout };
918 (res, nin, nout, nend)
919 }
920
921 #[inline(always)]
922 fn read_field_nfa(
923 &mut self,
924 input: &[u8],
925 output: &mut [u8],
926 ) -> (ReadFieldResult, usize, usize) {
927 if input.is_empty() {
928 self.nfa_state = self.transition_final_nfa(self.nfa_state);
929 let res = ReadFieldResult::from_nfa(self.nfa_state, false, false);
930 return (res, 0, 0);
931 }
932 if output.is_empty() {
933 return (ReadFieldResult::OutputFull, 0, 0);
936 }
937 let (mut nin, mut nout) = (0, 0);
938 let mut state = self.nfa_state;
939 while nin < input.len() && nout < output.len() {
940 let (s, io) = self.transition_nfa(state, input[nin]);
941 match io {
942 NfaInputAction::CopyToOutput => {
943 output[nout] = input[nin];
944 nout += 1;
945 nin += 1;
946 }
947 NfaInputAction::Discard => {
948 nin += 1;
949 }
950 NfaInputAction::Epsilon => (),
951 }
952 state = s;
953 if state.is_field_final() {
954 break;
955 }
956 }
957 let res = ReadFieldResult::from_nfa(
958 state,
959 nin >= input.len(),
960 nout >= output.len(),
961 );
962 self.nfa_state = state;
963 (res, nin, nout)
964 }
965
966 #[inline(always)]
969 fn transition_final_nfa(&self, state: NfaState) -> NfaState {
970 use self::NfaState::*;
971 match state {
972 End | StartRecord | EndRecord | InComment | CRLF => End,
973 StartField | EndFieldDelim | EndFieldTerm | InField
974 | InQuotedField | InEscapedQuote | InDoubleEscapedQuote
975 | InRecordTerm => EndRecord,
976 }
977 }
978
979 #[inline(always)]
986 fn transition_nfa(
987 &self,
988 state: NfaState,
989 c: u8,
990 ) -> (NfaState, NfaInputAction) {
991 use self::NfaState::*;
992 match state {
993 End => (End, NfaInputAction::Epsilon),
994 StartRecord => {
995 if self.term.equals(c) {
996 (StartRecord, NfaInputAction::Discard)
997 } else if self.comment == Some(c) {
998 (InComment, NfaInputAction::Discard)
999 } else {
1000 (StartField, NfaInputAction::Epsilon)
1001 }
1002 }
1003 EndRecord => (StartRecord, NfaInputAction::Epsilon),
1004 StartField => {
1005 if self.quoting && self.quote == c {
1006 (InQuotedField, NfaInputAction::Discard)
1007 } else if self.delimiter == c {
1008 (EndFieldDelim, NfaInputAction::Discard)
1009 } else if self.term.equals(c) {
1010 (EndFieldTerm, NfaInputAction::Epsilon)
1011 } else {
1012 (InField, NfaInputAction::CopyToOutput)
1013 }
1014 }
1015 EndFieldDelim => (StartField, NfaInputAction::Epsilon),
1016 EndFieldTerm => (InRecordTerm, NfaInputAction::Epsilon),
1017 InField => {
1018 if self.delimiter == c {
1019 (EndFieldDelim, NfaInputAction::Discard)
1020 } else if self.term.equals(c) {
1021 (EndFieldTerm, NfaInputAction::Epsilon)
1022 } else {
1023 (InField, NfaInputAction::CopyToOutput)
1024 }
1025 }
1026 InQuotedField => {
1027 if self.quoting && self.quote == c {
1028 (InDoubleEscapedQuote, NfaInputAction::Discard)
1029 } else if self.quoting && self.escape == Some(c) {
1030 (InEscapedQuote, NfaInputAction::Discard)
1031 } else {
1032 (InQuotedField, NfaInputAction::CopyToOutput)
1033 }
1034 }
1035 InEscapedQuote => (InQuotedField, NfaInputAction::CopyToOutput),
1036 InDoubleEscapedQuote => {
1037 if self.quoting && self.double_quote && self.quote == c {
1038 (InQuotedField, NfaInputAction::CopyToOutput)
1039 } else if self.delimiter == c {
1040 (EndFieldDelim, NfaInputAction::Discard)
1041 } else if self.term.equals(c) {
1042 (EndFieldTerm, NfaInputAction::Epsilon)
1043 } else {
1044 (InField, NfaInputAction::CopyToOutput)
1045 }
1046 }
1047 InComment => {
1048 if b'\n' == c {
1049 (StartRecord, NfaInputAction::Discard)
1050 } else {
1051 (InComment, NfaInputAction::Discard)
1052 }
1053 }
1054 InRecordTerm => {
1055 if self.term.is_crlf() && b'\r' == c {
1056 (CRLF, NfaInputAction::Discard)
1057 } else {
1058 (EndRecord, NfaInputAction::Discard)
1059 }
1060 }
1061 CRLF => {
1062 if b'\n' == c {
1063 (StartRecord, NfaInputAction::Discard)
1064 } else {
1065 (StartRecord, NfaInputAction::Epsilon)
1066 }
1067 }
1068 }
1069 }
1070}
1071
1072const TRANS_CLASSES: usize = 7;
1091const DFA_STATES: usize = 10;
1092const TRANS_SIZE: usize = TRANS_CLASSES * DFA_STATES;
1093
1094const CLASS_SIZE: usize = 256;
1097
1098struct Dfa {
1103 trans: [DfaState; TRANS_SIZE],
1110 has_output: [bool; TRANS_SIZE],
1114 classes: DfaClasses,
1119 in_field: DfaState,
1121 in_quoted: DfaState,
1123 final_field: DfaState,
1126 final_record: DfaState,
1129}
1130
1131impl Dfa {
1132 fn new() -> Dfa {
1133 Dfa {
1134 trans: [DfaState(0); TRANS_SIZE],
1135 has_output: [false; TRANS_SIZE],
1136 classes: DfaClasses::new(),
1137 in_field: DfaState(0),
1138 in_quoted: DfaState(0),
1139 final_field: DfaState(0),
1140 final_record: DfaState(0),
1141 }
1142 }
1143
1144 fn new_state(&self, nfa_state: NfaState) -> DfaState {
1145 let nclasses = self.classes.num_classes() as u8;
1146 let idx = (nfa_state as u8).checked_mul(nclasses).unwrap();
1147 DfaState(idx)
1148 }
1149
1150 fn new_state_final_end(&self) -> DfaState {
1151 self.new_state(NfaState::StartRecord)
1152 }
1153
1154 fn new_state_final_record(&self) -> DfaState {
1155 self.new_state(NfaState::EndRecord)
1156 }
1157
1158 fn get_output(&self, state: DfaState, c: u8) -> (DfaState, bool) {
1159 let cls = self.classes.classes[c as usize];
1160 let idx = state.0 as usize + cls as usize;
1161 (self.trans[idx], self.has_output[idx])
1162 }
1163
1164 fn set(&mut self, from: DfaState, c: u8, to: DfaState, output: bool) {
1165 let cls = self.classes.classes[c as usize];
1166 let idx = from.0 as usize + cls as usize;
1167 self.trans[idx] = to;
1168 self.has_output[idx] = output;
1169 }
1170
1171 fn finish(&mut self) {
1172 self.in_field = self.new_state(NfaState::InField);
1173 self.in_quoted = self.new_state(NfaState::InQuotedField);
1174 self.final_field = self.new_state(NfaState::EndFieldDelim);
1175 self.final_record = self.new_state(NfaState::EndRecord);
1176 }
1177
1178 fn new_read_field_result(
1179 &self,
1180 state: DfaState,
1181 is_final_trans: bool,
1182 inpdone: bool,
1183 outdone: bool,
1184 ) -> ReadFieldResult {
1185 if state >= self.final_record {
1186 ReadFieldResult::Field { record_end: true }
1187 } else if state == self.final_field {
1188 ReadFieldResult::Field { record_end: false }
1189 } else if is_final_trans && state.is_start() {
1190 ReadFieldResult::End
1191 } else {
1192 debug_assert!(state < self.final_field);
1193 if !inpdone && outdone {
1194 ReadFieldResult::OutputFull
1195 } else {
1196 ReadFieldResult::InputEmpty
1197 }
1198 }
1199 }
1200
1201 fn new_read_record_result(
1202 &self,
1203 state: DfaState,
1204 is_final_trans: bool,
1205 inpdone: bool,
1206 outdone: bool,
1207 endsdone: bool,
1208 ) -> ReadRecordResult {
1209 if state >= self.final_record {
1210 ReadRecordResult::Record
1211 } else if is_final_trans && state.is_start() {
1212 ReadRecordResult::End
1213 } else {
1214 debug_assert!(state < self.final_record);
1215 if !inpdone && outdone {
1216 ReadRecordResult::OutputFull
1217 } else if !inpdone && endsdone {
1218 ReadRecordResult::OutputEndsFull
1219 } else {
1220 ReadRecordResult::InputEmpty
1221 }
1222 }
1223 }
1224}
1225
1226struct DfaClasses {
1228 classes: [u8; CLASS_SIZE],
1229 next_class: usize,
1230}
1231
1232impl DfaClasses {
1233 fn new() -> DfaClasses {
1234 DfaClasses { classes: [0; CLASS_SIZE], next_class: 1 }
1235 }
1236
1237 fn add(&mut self, b: u8) {
1238 if self.next_class > CLASS_SIZE {
1239 panic!("added too many classes")
1240 }
1241 self.classes[b as usize] = self.next_class as u8;
1242 self.next_class = self.next_class + 1;
1243 }
1244
1245 fn num_classes(&self) -> usize {
1246 self.next_class as usize
1247 }
1248
1249 #[inline(always)]
1260 fn scan_and_copy(
1261 &self,
1262 input: &[u8],
1263 nin: &mut usize,
1264 output: &mut [u8],
1265 nout: &mut usize,
1266 ) {
1267 while *nin < input.len()
1268 && *nout < output.len()
1269 && self.classes[input[*nin] as usize] == 0
1270 {
1271 output[*nout] = input[*nin];
1272 *nin += 1;
1273 *nout += 1;
1274 }
1275 }
1276}
1277
1278#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
1285struct DfaState(u8);
1286
1287impl DfaState {
1288 fn start() -> DfaState {
1289 DfaState(0)
1290 }
1291
1292 fn is_start(&self) -> bool {
1293 self.0 == 0
1294 }
1295}
1296
1297impl fmt::Debug for Dfa {
1298 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1299 write!(f, "Dfa(N/A)")
1300 }
1301}
1302
1303impl fmt::Debug for DfaClasses {
1304 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1305 write!(
1306 f,
1307 "DfaClasses {{ classes: N/A, next_class: {:?} }}",
1308 self.next_class
1309 )
1310 }
1311}
1312
1313impl Clone for Dfa {
1314 fn clone(&self) -> Dfa {
1315 let mut dfa = Dfa::new();
1316 dfa.trans.copy_from_slice(&self.trans);
1317 dfa
1318 }
1319}
1320
1321impl Clone for DfaClasses {
1322 fn clone(&self) -> DfaClasses {
1323 let mut x = DfaClasses::new();
1324 x.classes.copy_from_slice(&self.classes);
1325 x
1326 }
1327}
1328
1329#[cfg(test)]
1330mod tests {
1331 use core::str;
1332
1333 use arrayvec::{ArrayString, ArrayVec};
1334
1335 use super::{ReadFieldResult, Reader, ReaderBuilder, Terminator};
1336
1337 type Csv = ArrayVec<[Row; 10]>;
1338 type Row = ArrayVec<[Field; 10]>;
1339 type Field = ArrayString<[u8; 10]>;
1340
1341 fn b(s: &str) -> &[u8] {
1343 s.as_bytes()
1344 }
1345
1346 macro_rules! csv {
1347 ($([$($field:expr),*]),*) => {{
1348 #[allow(unused_mut)]
1349 fn x() -> Csv {
1350 let mut csv = Csv::new();
1351 $(
1352 let mut row = Row::new();
1353 $(
1354 row.push(Field::from($field).unwrap());
1355 )*
1356 csv.push(row);
1357 )*
1358 csv
1359 }
1360 x()
1361 }}
1362 }
1363
1364 macro_rules! parses_to {
1365 ($name:ident, $data:expr, $expected:expr) => {
1366 parses_to!($name, $data, $expected, |builder| builder);
1367 };
1368 ($name:ident, $data:expr, $expected:expr, $config:expr) => {
1369 #[test]
1370 fn $name() {
1371 let mut builder = ReaderBuilder::new();
1372 builder.nfa(true);
1373 $config(&mut builder);
1374 let mut rdr = builder.build();
1375 let got = parse_by_field(&mut rdr, $data);
1376 let expected = $expected;
1377 assert_eq!(expected, got, "nfa by field");
1378
1379 let mut builder = ReaderBuilder::new();
1380 builder.nfa(true);
1381 $config(&mut builder);
1382 let mut rdr = builder.build();
1383 let got = parse_by_record(&mut rdr, $data);
1384 let expected = $expected;
1385 assert_eq!(expected, got, "nfa by record");
1386
1387 let mut builder = ReaderBuilder::new();
1388 $config(&mut builder);
1389 let mut rdr = builder.build();
1390 let got = parse_by_field(&mut rdr, $data);
1391 let expected = $expected;
1392 assert_eq!(expected, got, "dfa by field");
1393
1394 let mut builder = ReaderBuilder::new();
1395 $config(&mut builder);
1396 let mut rdr = builder.build();
1397 let got = parse_by_record(&mut rdr, $data);
1398 let expected = $expected;
1399 assert_eq!(expected, got, "dfa by record");
1400 }
1401 };
1402 }
1403
1404 fn parse_by_field(rdr: &mut Reader, data: &str) -> Csv {
1405 let mut data = data.as_bytes();
1406 let mut field = [0u8; 10];
1407 let mut csv = Csv::new();
1408 let mut row = Row::new();
1409 let mut outpos = 0;
1410 loop {
1411 let (res, nin, nout) = rdr.read_field(data, &mut field[outpos..]);
1412 data = &data[nin..];
1413 outpos += nout;
1414
1415 match res {
1416 ReadFieldResult::InputEmpty => {
1417 if !data.is_empty() {
1418 panic!("missing input data")
1419 }
1420 }
1421 ReadFieldResult::OutputFull => panic!("field too large"),
1422 ReadFieldResult::Field { record_end } => {
1423 let s = str::from_utf8(&field[..outpos]).unwrap();
1424 row.push(Field::from(s).unwrap());
1425 outpos = 0;
1426 if record_end {
1427 csv.push(row);
1428 row = Row::new();
1429 }
1430 }
1431 ReadFieldResult::End => {
1432 return csv;
1433 }
1434 }
1435 }
1436 }
1437
1438 fn parse_by_record(rdr: &mut Reader, data: &str) -> Csv {
1439 use crate::ReadRecordResult::*;
1440
1441 let mut data = data.as_bytes();
1442 let mut record = [0; 1024];
1443 let mut ends = [0; 10];
1444
1445 let mut csv = Csv::new();
1446 let (mut outpos, mut endpos) = (0, 0);
1447 loop {
1448 let (res, nin, nout, nend) = rdr.read_record(
1449 data,
1450 &mut record[outpos..],
1451 &mut ends[endpos..],
1452 );
1453 data = &data[nin..];
1454 outpos += nout;
1455 endpos += nend;
1456
1457 match res {
1458 InputEmpty => {
1459 if !data.is_empty() {
1460 panic!("missing input data")
1461 }
1462 }
1463 OutputFull => panic!("record too large (out buffer)"),
1464 OutputEndsFull => panic!("record too large (end buffer)"),
1465 Record => {
1466 let s = str::from_utf8(&record[..outpos]).unwrap();
1467 let mut start = 0;
1468 let mut row = Row::new();
1469 for &end in &ends[..endpos] {
1470 row.push(Field::from(&s[start..end]).unwrap());
1471 start = end;
1472 }
1473 csv.push(row);
1474 outpos = 0;
1475 endpos = 0;
1476 }
1477 End => return csv,
1478 }
1479 }
1480 }
1481
1482 parses_to!(one_row_one_field, "a", csv![["a"]]);
1483 parses_to!(one_row_many_fields, "a,b,c", csv![["a", "b", "c"]]);
1484 parses_to!(one_row_trailing_comma, "a,b,", csv![["a", "b", ""]]);
1485 parses_to!(one_row_one_field_lf, "a\n", csv![["a"]]);
1486 parses_to!(one_row_many_fields_lf, "a,b,c\n", csv![["a", "b", "c"]]);
1487 parses_to!(one_row_trailing_comma_lf, "a,b,\n", csv![["a", "b", ""]]);
1488 parses_to!(one_row_one_field_crlf, "a\r\n", csv![["a"]]);
1489 parses_to!(one_row_many_fields_crlf, "a,b,c\r\n", csv![["a", "b", "c"]]);
1490 parses_to!(one_row_trailing_comma_crlf, "a,b,\r\n", csv![["a", "b", ""]]);
1491 parses_to!(one_row_one_field_cr, "a\r", csv![["a"]]);
1492 parses_to!(one_row_many_fields_cr, "a,b,c\r", csv![["a", "b", "c"]]);
1493 parses_to!(one_row_trailing_comma_cr, "a,b,\r", csv![["a", "b", ""]]);
1494
1495 parses_to!(many_rows_one_field, "a\nb", csv![["a"], ["b"]]);
1496 parses_to!(
1497 many_rows_many_fields,
1498 "a,b,c\nx,y,z",
1499 csv![["a", "b", "c"], ["x", "y", "z"]]
1500 );
1501 parses_to!(
1502 many_rows_trailing_comma,
1503 "a,b,\nx,y,",
1504 csv![["a", "b", ""], ["x", "y", ""]]
1505 );
1506 parses_to!(many_rows_one_field_lf, "a\nb\n", csv![["a"], ["b"]]);
1507 parses_to!(
1508 many_rows_many_fields_lf,
1509 "a,b,c\nx,y,z\n",
1510 csv![["a", "b", "c"], ["x", "y", "z"]]
1511 );
1512 parses_to!(
1513 many_rows_trailing_comma_lf,
1514 "a,b,\nx,y,\n",
1515 csv![["a", "b", ""], ["x", "y", ""]]
1516 );
1517 parses_to!(many_rows_one_field_crlf, "a\r\nb\r\n", csv![["a"], ["b"]]);
1518 parses_to!(
1519 many_rows_many_fields_crlf,
1520 "a,b,c\r\nx,y,z\r\n",
1521 csv![["a", "b", "c"], ["x", "y", "z"]]
1522 );
1523 parses_to!(
1524 many_rows_trailing_comma_crlf,
1525 "a,b,\r\nx,y,\r\n",
1526 csv![["a", "b", ""], ["x", "y", ""]]
1527 );
1528 parses_to!(many_rows_one_field_cr, "a\rb\r", csv![["a"], ["b"]]);
1529 parses_to!(
1530 many_rows_many_fields_cr,
1531 "a,b,c\rx,y,z\r",
1532 csv![["a", "b", "c"], ["x", "y", "z"]]
1533 );
1534 parses_to!(
1535 many_rows_trailing_comma_cr,
1536 "a,b,\rx,y,\r",
1537 csv![["a", "b", ""], ["x", "y", ""]]
1538 );
1539
1540 parses_to!(
1541 trailing_lines_no_record,
1542 "\n\n\na,b,c\nx,y,z\n\n\n",
1543 csv![["a", "b", "c"], ["x", "y", "z"]]
1544 );
1545 parses_to!(
1546 trailing_lines_no_record_cr,
1547 "\r\r\ra,b,c\rx,y,z\r\r\r",
1548 csv![["a", "b", "c"], ["x", "y", "z"]]
1549 );
1550 parses_to!(
1551 trailing_lines_no_record_crlf,
1552 "\r\n\r\n\r\na,b,c\r\nx,y,z\r\n\r\n\r\n",
1553 csv![["a", "b", "c"], ["x", "y", "z"]]
1554 );
1555
1556 parses_to!(empty, "", csv![]);
1557 parses_to!(empty_lines, "\n\n\n\n", csv![]);
1558 parses_to!(
1559 empty_lines_interspersed,
1560 "\n\na,b\n\n\nx,y\n\n\nm,n\n",
1561 csv![["a", "b"], ["x", "y"], ["m", "n"]]
1562 );
1563 parses_to!(empty_lines_crlf, "\r\n\r\n\r\n\r\n", csv![]);
1564 parses_to!(
1565 empty_lines_interspersed_crlf,
1566 "\r\n\r\na,b\r\n\r\n\r\nx,y\r\n\r\n\r\nm,n\r\n",
1567 csv![["a", "b"], ["x", "y"], ["m", "n"]]
1568 );
1569 parses_to!(empty_lines_mixed, "\r\n\n\r\n\n", csv![]);
1570 parses_to!(
1571 empty_lines_interspersed_mixed,
1572 "\n\r\na,b\r\n\n\r\nx,y\r\n\n\r\nm,n\r\n",
1573 csv![["a", "b"], ["x", "y"], ["m", "n"]]
1574 );
1575 parses_to!(empty_lines_cr, "\r\r\r\r", csv![]);
1576 parses_to!(
1577 empty_lines_interspersed_cr,
1578 "\r\ra,b\r\r\rx,y\r\r\rm,n\r",
1579 csv![["a", "b"], ["x", "y"], ["m", "n"]]
1580 );
1581
1582 parses_to!(
1583 term_weird,
1584 "zza,bzc,dzz",
1585 csv![["a", "b"], ["c", "d"]],
1586 |b: &mut ReaderBuilder| {
1587 b.terminator(Terminator::Any(b'z'));
1588 }
1589 );
1590
1591 parses_to!(
1592 ascii_delimited,
1593 "a\x1fb\x1ec\x1fd",
1594 csv![["a", "b"], ["c", "d"]],
1595 |b: &mut ReaderBuilder| {
1596 b.ascii();
1597 }
1598 );
1599
1600 parses_to!(bom_at_start, "\u{feff}a", csv![["a"]]);
1601 parses_to!(bom_in_field, "a\u{feff}", csv![["a\u{feff}"]]);
1602 parses_to!(bom_at_field_start, "a,\u{feff}b", csv![["a", "\u{feff}b"]]);
1603
1604 parses_to!(quote_empty, "\"\"", csv![[""]]);
1605 parses_to!(quote_lf, "\"\"\n", csv![[""]]);
1606 parses_to!(quote_space, "\" \"", csv![[" "]]);
1607 parses_to!(quote_inner_space, "\" a \"", csv![[" a "]]);
1608 parses_to!(quote_outer_space, " \"a\" ", csv![[" \"a\" "]]);
1609
1610 parses_to!(quote_change, "zaz", csv![["a"]], |b: &mut ReaderBuilder| {
1611 b.quote(b'z');
1612 });
1613
1614 parses_to!(
1617 quote_delimiter,
1618 ",a,,b",
1619 csv![["a,b"]],
1620 |b: &mut ReaderBuilder| {
1621 b.quote(b',');
1622 }
1623 );
1624
1625 parses_to!(quote_no_escapes, r#""a\"b""#, csv![[r#"a\b""#]]);
1626 parses_to!(
1627 quote_escapes_no_double,
1628 r#""a""b""#,
1629 csv![[r#"a"b""#]],
1630 |b: &mut ReaderBuilder| {
1631 b.double_quote(false);
1632 }
1633 );
1634 parses_to!(
1635 quote_escapes,
1636 r#""a\"b""#,
1637 csv![[r#"a"b"#]],
1638 |b: &mut ReaderBuilder| {
1639 b.escape(Some(b'\\'));
1640 }
1641 );
1642 parses_to!(
1643 quote_escapes_change,
1644 r#""az"b""#,
1645 csv![[r#"a"b"#]],
1646 |b: &mut ReaderBuilder| {
1647 b.escape(Some(b'z'));
1648 }
1649 );
1650
1651 parses_to!(
1652 quote_escapes_with_comma,
1653 r#""\"A,B\"""#,
1654 csv![[r#""A,B""#]],
1655 |b: &mut ReaderBuilder| {
1656 b.escape(Some(b'\\')).double_quote(false);
1657 }
1658 );
1659
1660 parses_to!(
1661 quoting_disabled,
1662 r#""abc,foo""#,
1663 csv![[r#""abc"#, r#"foo""#]],
1664 |b: &mut ReaderBuilder| {
1665 b.quoting(false);
1666 }
1667 );
1668
1669 parses_to!(
1670 delimiter_tabs,
1671 "a\tb",
1672 csv![["a", "b"]],
1673 |b: &mut ReaderBuilder| {
1674 b.delimiter(b'\t');
1675 }
1676 );
1677 parses_to!(
1678 delimiter_weird,
1679 "azb",
1680 csv![["a", "b"]],
1681 |b: &mut ReaderBuilder| {
1682 b.delimiter(b'z');
1683 }
1684 );
1685
1686 parses_to!(extra_record_crlf_1, "foo\n1\n", csv![["foo"], ["1"]]);
1687 parses_to!(extra_record_crlf_2, "foo\r\n1\r\n", csv![["foo"], ["1"]]);
1688
1689 parses_to!(
1690 comment_1,
1691 "foo\n# hi\nbar\n",
1692 csv![["foo"], ["bar"]],
1693 |b: &mut ReaderBuilder| {
1694 b.comment(Some(b'#'));
1695 }
1696 );
1697 parses_to!(
1698 comment_2,
1699 "foo\n # hi\nbar\n",
1700 csv![["foo"], [" # hi"], ["bar"]],
1701 |b: &mut ReaderBuilder| {
1702 b.comment(Some(b'#'));
1703 }
1704 );
1705 parses_to!(
1706 comment_3,
1707 "foo\n# hi\nbar\n",
1708 csv![["foo"], ["# hi"], ["bar"]],
1709 |b: &mut ReaderBuilder| {
1710 b.comment(Some(b'\n'));
1711 }
1712 );
1713 parses_to!(
1714 comment_4,
1715 "foo,b#ar,baz",
1716 csv![["foo", "b#ar", "baz"]],
1717 |b: &mut ReaderBuilder| {
1718 b.comment(Some(b'#'));
1719 }
1720 );
1721 parses_to!(
1722 comment_5,
1723 "foo,#bar,baz",
1724 csv![["foo", "#bar", "baz"]],
1725 |b: &mut ReaderBuilder| {
1726 b.comment(Some(b'#'));
1727 }
1728 );
1729
1730 macro_rules! assert_read {
1731 (
1732 $rdr:expr, $input:expr, $output:expr,
1733 $expect_in:expr, $expect_out:expr, $expect_res:expr
1734 ) => {{
1735 let (res, nin, nout) = $rdr.read_field($input, $output);
1736 assert_eq!($expect_in, nin);
1737 assert_eq!($expect_out, nout);
1738 assert_eq!($expect_res, res);
1739 }};
1740 }
1741
1742 #[test]
1745 fn stream_empty() {
1746 use crate::ReadFieldResult::*;
1747
1748 let mut rdr = Reader::new();
1749 assert_read!(rdr, &[], &mut [], 0, 0, End);
1750 }
1751
1752 #[test]
1754 fn stream_space() {
1755 use crate::ReadFieldResult::*;
1756
1757 let mut rdr = Reader::new();
1758 assert_read!(rdr, b(" "), &mut [0], 1, 1, InputEmpty);
1759 assert_read!(rdr, &[], &mut [0], 0, 0, Field { record_end: true });
1760 assert_read!(rdr, &[], &mut [0], 0, 0, End);
1761 }
1762
1763 #[test]
1765 fn stream_comma() {
1766 use crate::ReadFieldResult::*;
1767
1768 let mut rdr = Reader::new();
1769 assert_read!(rdr, b(","), &mut [0], 1, 0, Field { record_end: false });
1770 assert_read!(rdr, &[], &mut [0], 0, 0, Field { record_end: true });
1771 assert_read!(rdr, &[], &mut [0], 0, 0, End);
1772 }
1773
1774 #[test]
1777 fn stream_output_chunks() {
1778 use crate::ReadFieldResult::*;
1779
1780 let mut inp = b("fooquux");
1781 let out = &mut [0; 2];
1782 let mut rdr = Reader::new();
1783
1784 assert_read!(rdr, inp, out, 2, 2, OutputFull);
1785 assert_eq!(out, b("fo"));
1786 inp = &inp[2..];
1787
1788 assert_read!(rdr, inp, out, 2, 2, OutputFull);
1789 assert_eq!(out, b("oq"));
1790 inp = &inp[2..];
1791
1792 assert_read!(rdr, inp, out, 2, 2, OutputFull);
1793 assert_eq!(out, b("uu"));
1794 inp = &inp[2..];
1795
1796 assert_read!(rdr, inp, out, 1, 1, InputEmpty);
1797 assert_eq!(&out[..1], b("x"));
1798 inp = &inp[1..];
1799 assert!(inp.is_empty());
1800
1801 assert_read!(rdr, &[], out, 0, 0, Field { record_end: true });
1802 assert_read!(rdr, inp, out, 0, 0, End);
1803 }
1804
1805 #[test]
1808 fn stream_input_chunks() {
1809 use crate::ReadFieldResult::*;
1810
1811 let out = &mut [0; 10];
1812 let mut rdr = Reader::new();
1813
1814 assert_read!(rdr, b("fo"), out, 2, 2, InputEmpty);
1815 assert_eq!(&out[..2], b("fo"));
1816
1817 assert_read!(rdr, b("oq"), &mut out[2..], 2, 2, InputEmpty);
1818 assert_eq!(&out[..4], b("fooq"));
1819
1820 assert_read!(rdr, b("uu"), &mut out[4..], 2, 2, InputEmpty);
1821 assert_eq!(&out[..6], b("fooquu"));
1822
1823 assert_read!(rdr, b("x"), &mut out[6..], 1, 1, InputEmpty);
1824 assert_eq!(&out[..7], b("fooquux"));
1825
1826 assert_read!(rdr, &[], out, 0, 0, Field { record_end: true });
1827 assert_read!(rdr, &[], out, 0, 0, End);
1828 }
1829
1830 #[test]
1832 fn stream_doubled_quotes() {
1833 use crate::ReadFieldResult::*;
1834
1835 let out = &mut [0; 10];
1836 let mut rdr = Reader::new();
1837
1838 assert_read!(rdr, b("\"fo\""), out, 4, 2, InputEmpty);
1839 assert_eq!(&out[..2], b("fo"));
1840
1841 assert_read!(rdr, b("\"o"), &mut out[2..], 2, 2, InputEmpty);
1842 assert_eq!(&out[..4], b("fo\"o"));
1843
1844 assert_read!(rdr, &[], out, 0, 0, Field { record_end: true });
1845 assert_read!(rdr, &[], out, 0, 0, End);
1846 }
1847
1848 #[test]
1850 fn stream_escaped_quotes() {
1851 use crate::ReadFieldResult::*;
1852
1853 let out = &mut [0; 10];
1854 let mut builder = ReaderBuilder::new();
1855 let mut rdr = builder.escape(Some(b'\\')).build();
1856
1857 assert_read!(rdr, b("\"fo\\"), out, 4, 2, InputEmpty);
1858 assert_eq!(&out[..2], b("fo"));
1859
1860 assert_read!(rdr, b("\"o"), &mut out[2..], 2, 2, InputEmpty);
1861 assert_eq!(&out[..4], b("fo\"o"));
1862
1863 assert_read!(rdr, &[], out, 0, 0, Field { record_end: true });
1864 assert_read!(rdr, &[], out, 0, 0, End);
1865 }
1866
1867 #[test]
1869 fn stream_empty_output() {
1870 use crate::ReadFieldResult::*;
1871
1872 let out = &mut [0; 10];
1873 let mut rdr = Reader::new();
1874
1875 assert_read!(
1876 rdr,
1877 b("foo,bar"),
1878 out,
1879 4,
1880 3,
1881 Field { record_end: false }
1882 );
1883 assert_eq!(&out[..3], b("foo"));
1884
1885 assert_read!(rdr, b("bar"), &mut [], 0, 0, OutputFull);
1886
1887 assert_read!(rdr, b("bar"), out, 3, 3, InputEmpty);
1888 assert_eq!(&out[..3], b("bar"));
1889
1890 assert_read!(rdr, &[], out, 0, 0, Field { record_end: true });
1891 assert_read!(rdr, &[], out, 0, 0, End);
1892 }
1893
1894 #[test]
1897 fn reset_works() {
1898 use crate::ReadFieldResult::*;
1899
1900 let out = &mut [0; 10];
1901 let mut rdr = Reader::new();
1902
1903 assert_read!(rdr, b("\"foo"), out, 4, 3, InputEmpty);
1904 assert_eq!(&out[..3], b("foo"));
1905
1906 rdr.reset();
1914
1915 assert_read!(rdr, b("\"\"bar\""), out, 6, 4, InputEmpty);
1916 assert_eq!(&out[..4], b("bar\""));
1917 }
1918
1919 #[test]
1921 fn line_numbers() {
1922 use crate::ReadFieldResult::*;
1923
1924 let out = &mut [0; 10];
1925 let mut rdr = Reader::new();
1926
1927 assert_eq!(1, rdr.line());
1928
1929 assert_read!(rdr, b("\n\n\n\n"), out, 4, 0, InputEmpty);
1930 assert_eq!(5, rdr.line());
1931
1932 assert_read!(rdr, b("foo,"), out, 4, 3, Field { record_end: false });
1933 assert_eq!(5, rdr.line());
1934
1935 assert_read!(rdr, b("bar\n"), out, 4, 3, Field { record_end: true });
1936 assert_eq!(6, rdr.line());
1937
1938 assert_read!(rdr, &[], &mut [0], 0, 0, End);
1939 assert_eq!(6, rdr.line());
1940 }
1941
1942 macro_rules! assert_read_record {
1943 (
1944 $rdr:expr, $input:expr, $output:expr, $ends:expr,
1945 $expect_in:expr, $expect_out:expr,
1946 $expect_end:expr, $expect_res:expr
1947 ) => {{
1948 let (res, nin, nout, nend) =
1949 $rdr.read_record($input, $output, $ends);
1950 assert_eq!($expect_res, res, "result");
1951 assert_eq!($expect_in, nin, "input");
1952 assert_eq!($expect_out, nout, "output");
1953 assert_eq!($expect_end, nend, "ends");
1954 }};
1955 }
1956
1957 #[test]
1959 fn stream_record() {
1960 use crate::ReadRecordResult::*;
1961
1962 let mut inp = b("foo,bar\nbaz");
1963 let out = &mut [0; 1024];
1964 let ends = &mut [0; 10];
1965 let mut rdr = Reader::new();
1966
1967 assert_read_record!(rdr, &inp, out, ends, 8, 6, 2, Record);
1968 assert_eq!(ends[0], 3);
1969 assert_eq!(ends[1], 6);
1970 inp = &inp[8..];
1971
1972 assert_read_record!(rdr, &inp, out, ends, 3, 3, 0, InputEmpty);
1973 inp = &inp[3..];
1974
1975 assert_read_record!(rdr, &inp, out, ends, 0, 0, 1, Record);
1976 assert_eq!(ends[0], 3);
1977
1978 assert_read_record!(rdr, &inp, out, ends, 0, 0, 0, End);
1979 }
1980
1981 #[test]
1984 fn stream_record_last_end_output_full() {
1985 use crate::ReadRecordResult::*;
1986
1987 let mut inp = b("foo,bar\nbaz");
1988 let out = &mut [0; 1024];
1989 let ends = &mut [0; 10];
1990 let mut rdr = Reader::new();
1991
1992 assert_read_record!(rdr, &inp, out, ends, 8, 6, 2, Record);
1993 assert_eq!(ends[0], 3);
1994 assert_eq!(ends[1], 6);
1995 inp = &inp[8..];
1996
1997 assert_read_record!(rdr, &inp, out, ends, 3, 3, 0, InputEmpty);
1998 inp = &inp[3..];
1999
2000 assert_read_record!(rdr, &inp, out, &mut [], 0, 0, 0, OutputEndsFull);
2001 assert_read_record!(rdr, &inp, out, ends, 0, 0, 1, Record);
2002 assert_eq!(ends[0], 3);
2003
2004 assert_read_record!(rdr, &inp, out, ends, 0, 0, 0, End);
2005 }
2006
2007 #[test]
2008 fn reset_input_partial() {
2009 use crate::ReadRecordResult::*;
2010
2011 let inp = b("foo,bar\nbaz");
2012 let out = &mut [0; 1024];
2013 let ends = &mut [0; 10];
2014 let mut rdr = Reader::new();
2015
2016 assert_read_record!(rdr, &inp, out, ends, 8, 6, 2, Record);
2017
2018 let (result, _, _, _) = rdr.read_record(&inp[8..], out, ends);
2020 assert_eq!(result, InputEmpty);
2021
2022 rdr.reset();
2023
2024 let inp = b("baz,raz\n");
2025 let (result, _, _, _) = rdr.read_record(inp, out, ends);
2026 assert_eq!(result, Record);
2027 assert_eq!(ends[0], 3);
2028 }
2029}