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: &[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 matches!(
459 *self,
460 NfaState::End
461 | NfaState::EndRecord
462 | NfaState::CRLF
463 | NfaState::EndFieldDelim
464 )
465 }
466
467 fn is_record_final(&self) -> bool {
469 matches!(*self, NfaState::End | NfaState::EndRecord | NfaState::CRLF)
470 }
471}
472
473impl Reader {
474 pub fn new() -> Reader {
476 ReaderBuilder::new().build()
477 }
478
479 pub fn reset(&mut self) {
483 self.dfa_state = self.dfa.new_state(NfaState::StartRecord);
484 self.nfa_state = NfaState::StartRecord;
485 self.line = 1;
486 self.has_read = false;
487 self.output_pos = 0;
488 }
489
490 pub fn line(&self) -> u64 {
495 self.line
496 }
497
498 pub fn set_line(&mut self, line: u64) {
503 self.line = line;
504 }
505
506 pub fn read_field(
536 &mut self,
537 input: &[u8],
538 output: &mut [u8],
539 ) -> (ReadFieldResult, usize, usize) {
540 let (input, bom_nin) = self.strip_utf8_bom(input);
541 let (res, nin, nout) = if self.use_nfa {
542 self.read_field_nfa(input, output)
543 } else {
544 self.read_field_dfa(input, output)
545 };
546 self.has_read = true;
547 (res, nin + bom_nin, nout)
548 }
549
550 pub fn read_record(
592 &mut self,
593 input: &[u8],
594 output: &mut [u8],
595 ends: &mut [usize],
596 ) -> (ReadRecordResult, usize, usize, usize) {
597 let (input, bom_nin) = self.strip_utf8_bom(input);
598 let (res, nin, nout, nend) = if self.use_nfa {
599 self.read_record_nfa(input, output, ends)
600 } else {
601 self.read_record_dfa(input, output, ends)
602 };
603 self.has_read = true;
604 (res, nin + bom_nin, nout, nend)
605 }
606
607 fn strip_utf8_bom<'a>(&self, input: &'a [u8]) -> (&'a [u8], usize) {
611 if !self.has_read
612 && input.len() >= 3
613 && &input[0..3] == b"\xef\xbb\xbf"
614 {
615 (&input[3..], 3)
616 } else {
617 (input, 0)
618 }
619 }
620
621 #[inline(always)]
622 fn read_record_dfa(
623 &mut self,
624 input: &[u8],
625 output: &mut [u8],
626 ends: &mut [usize],
627 ) -> (ReadRecordResult, usize, usize, usize) {
628 if input.is_empty() {
629 let s = self.transition_final_dfa(self.dfa_state);
630 let res =
631 self.dfa.new_read_record_result(s, true, false, false, false);
632 return match res {
640 ReadRecordResult::Record => {
641 if ends.is_empty() {
642 return (ReadRecordResult::OutputEndsFull, 0, 0, 0);
643 }
644 self.dfa_state = s;
645 ends[0] = self.output_pos;
646 self.output_pos = 0;
647 (res, 0, 0, 1)
648 }
649 _ => {
650 self.dfa_state = s;
651 (res, 0, 0, 0)
652 }
653 };
654 }
655 if output.is_empty() {
656 return (ReadRecordResult::OutputFull, 0, 0, 0);
657 }
658 if ends.is_empty() {
659 return (ReadRecordResult::OutputEndsFull, 0, 0, 0);
660 }
661 let (mut nin, mut nout, mut nend) = (0, 0, 0);
662 let mut state = self.dfa_state;
663 while nin < input.len() && nout < output.len() && nend < ends.len() {
664 let (s, has_out) = self.dfa.get_output(state, input[nin]);
665 self.line += (input[nin] == b'\n') as u64;
666 state = s;
667 if has_out {
668 output[nout] = input[nin];
669 nout += 1;
670 }
671 nin += 1;
672 if state >= self.dfa.final_field {
673 ends[nend] = self.output_pos + nout;
674 nend += 1;
675 if state > self.dfa.final_field {
676 break;
677 }
678 }
679 if state == self.dfa.in_field || state == self.dfa.in_quoted {
680 self.dfa
681 .classes
682 .scan_and_copy(input, &mut nin, output, &mut nout);
683 }
684 }
685 let res = self.dfa.new_read_record_result(
686 state,
687 false,
688 nin >= input.len(),
689 nout >= output.len(),
690 nend >= ends.len(),
691 );
692 self.dfa_state = state;
693 if res.is_record() {
694 self.output_pos = 0;
695 } else {
696 self.output_pos += nout;
697 }
698 (res, nin, nout, nend)
699 }
700
701 #[inline(always)]
702 fn read_field_dfa(
703 &mut self,
704 input: &[u8],
705 output: &mut [u8],
706 ) -> (ReadFieldResult, usize, usize) {
707 if input.is_empty() {
708 self.dfa_state = self.transition_final_dfa(self.dfa_state);
709 let res = self.dfa.new_read_field_result(
710 self.dfa_state,
711 true,
712 false,
713 false,
714 );
715 return (res, 0, 0);
716 }
717 if output.is_empty() {
718 return (ReadFieldResult::OutputFull, 0, 0);
719 }
720 let (mut nin, mut nout) = (0, 0);
721 let mut state = self.dfa_state;
722 while nin < input.len() && nout < output.len() {
723 let b = input[nin];
724 self.line += (b == b'\n') as u64;
725 let (s, has_out) = self.dfa.get_output(state, b);
726 state = s;
727 if has_out {
728 output[nout] = b;
729 nout += 1;
730 }
731 nin += 1;
732 if state >= self.dfa.final_field {
733 break;
734 }
735 }
736 let res = self.dfa.new_read_field_result(
737 state,
738 false,
739 nin >= input.len(),
740 nout >= output.len(),
741 );
742 self.dfa_state = state;
743 (res, nin, nout)
744 }
745
746 fn transition_final_dfa(&self, state: DfaState) -> DfaState {
749 if state >= self.dfa.final_record || state.is_start() {
754 self.dfa.new_state_final_end()
755 } else {
756 self.dfa.new_state_final_record()
757 }
758 }
759
760 fn build_dfa(&mut self) {
763 self.dfa.classes.add(self.delimiter);
802 if self.quoting {
803 self.dfa.classes.add(self.quote);
804 if let Some(escape) = self.escape {
805 self.dfa.classes.add(escape);
806 }
807 }
808 if let Some(comment) = self.comment {
809 self.dfa.classes.add(comment);
810 }
811 match self.term {
812 Terminator::Any(b) => self.dfa.classes.add(b),
813 Terminator::CRLF => {
814 self.dfa.classes.add(b'\r');
815 self.dfa.classes.add(b'\n');
816 }
817 }
818 for &state in NFA_STATES {
821 for c in (0..256).map(|c| c as u8) {
822 let mut nfa_result = (state, NfaInputAction::Epsilon);
823 while nfa_result.0 != NfaState::End
825 && nfa_result.1 == NfaInputAction::Epsilon
826 {
827 nfa_result = self.transition_nfa(nfa_result.0, c);
828 }
829 let from = self.dfa.new_state(state);
830 let to = self.dfa.new_state(nfa_result.0);
831 self.dfa.set(
832 from,
833 c,
834 to,
835 nfa_result.1 == NfaInputAction::CopyToOutput,
836 );
837 }
838 }
839 self.dfa_state = self.dfa.new_state(NfaState::StartRecord);
840 self.dfa.finish();
841 }
842
843 #[inline(always)]
849 fn read_record_nfa(
850 &mut self,
851 input: &[u8],
852 output: &mut [u8],
853 ends: &mut [usize],
854 ) -> (ReadRecordResult, usize, usize, usize) {
855 if input.is_empty() {
856 let s = self.transition_final_nfa(self.nfa_state);
857 let res = ReadRecordResult::from_nfa(s, false, false, false);
858 return match res {
859 ReadRecordResult::Record => {
860 if ends.is_empty() {
861 return (ReadRecordResult::OutputEndsFull, 0, 0, 0);
862 }
863 self.nfa_state = s;
864 ends[0] = self.output_pos;
865 self.output_pos = 0;
866 (res, 0, 0, 1)
867 }
868 _ => {
869 self.nfa_state = s;
870 (res, 0, 0, 0)
871 }
872 };
873 }
874 if output.is_empty() {
875 return (ReadRecordResult::OutputFull, 0, 0, 0);
876 }
877 if ends.is_empty() {
878 return (ReadRecordResult::OutputEndsFull, 0, 0, 0);
879 }
880 let (mut nin, mut nout, mut nend) = (0, self.output_pos, 0);
881 let mut state = self.nfa_state;
882 while nin < input.len() && nout < output.len() && nend < ends.len() {
883 let (s, io) = self.transition_nfa(state, input[nin]);
884 match io {
885 NfaInputAction::CopyToOutput => {
886 output[nout] = input[nin];
887 nout += 1;
888 nin += 1;
889 }
890 NfaInputAction::Discard => {
891 nin += 1;
892 }
893 NfaInputAction::Epsilon => {}
894 }
895 state = s;
896 if state.is_field_final() {
897 ends[nend] = nout;
898 nend += 1;
899 if state != NfaState::EndFieldDelim {
900 break;
901 }
902 }
903 }
904 let res = ReadRecordResult::from_nfa(
905 state,
906 nin >= input.len(),
907 nout >= output.len(),
908 nend >= ends.len(),
909 );
910 self.nfa_state = state;
911 self.output_pos = if res.is_record() { 0 } else { nout };
912 (res, nin, nout, nend)
913 }
914
915 #[inline(always)]
916 fn read_field_nfa(
917 &mut self,
918 input: &[u8],
919 output: &mut [u8],
920 ) -> (ReadFieldResult, usize, usize) {
921 if input.is_empty() {
922 self.nfa_state = self.transition_final_nfa(self.nfa_state);
923 let res = ReadFieldResult::from_nfa(self.nfa_state, false, false);
924 return (res, 0, 0);
925 }
926 if output.is_empty() {
927 return (ReadFieldResult::OutputFull, 0, 0);
930 }
931 let (mut nin, mut nout) = (0, 0);
932 let mut state = self.nfa_state;
933 while nin < input.len() && nout < output.len() {
934 let (s, io) = self.transition_nfa(state, input[nin]);
935 match io {
936 NfaInputAction::CopyToOutput => {
937 output[nout] = input[nin];
938 nout += 1;
939 nin += 1;
940 }
941 NfaInputAction::Discard => {
942 nin += 1;
943 }
944 NfaInputAction::Epsilon => (),
945 }
946 state = s;
947 if state.is_field_final() {
948 break;
949 }
950 }
951 let res = ReadFieldResult::from_nfa(
952 state,
953 nin >= input.len(),
954 nout >= output.len(),
955 );
956 self.nfa_state = state;
957 (res, nin, nout)
958 }
959
960 #[inline(always)]
963 fn transition_final_nfa(&self, state: NfaState) -> NfaState {
964 use self::NfaState::*;
965 match state {
966 End | StartRecord | EndRecord | InComment | CRLF => End,
967 StartField | EndFieldDelim | EndFieldTerm | InField
968 | InQuotedField | InEscapedQuote | InDoubleEscapedQuote
969 | InRecordTerm => EndRecord,
970 }
971 }
972
973 #[inline(always)]
980 fn transition_nfa(
981 &self,
982 state: NfaState,
983 c: u8,
984 ) -> (NfaState, NfaInputAction) {
985 use self::NfaState::*;
986 match state {
987 End => (End, NfaInputAction::Epsilon),
988 StartRecord => {
989 if self.term.equals(c) {
990 (StartRecord, NfaInputAction::Discard)
991 } else if self.comment == Some(c) {
992 (InComment, NfaInputAction::Discard)
993 } else {
994 (StartField, NfaInputAction::Epsilon)
995 }
996 }
997 EndRecord => (StartRecord, NfaInputAction::Epsilon),
998 StartField => {
999 if self.quoting && self.quote == c {
1000 (InQuotedField, NfaInputAction::Discard)
1001 } else if self.delimiter == c {
1002 (EndFieldDelim, NfaInputAction::Discard)
1003 } else if self.term.equals(c) {
1004 (EndFieldTerm, NfaInputAction::Epsilon)
1005 } else {
1006 (InField, NfaInputAction::CopyToOutput)
1007 }
1008 }
1009 EndFieldDelim => (StartField, NfaInputAction::Epsilon),
1010 EndFieldTerm => (InRecordTerm, NfaInputAction::Epsilon),
1011 InField => {
1012 if self.delimiter == c {
1013 (EndFieldDelim, NfaInputAction::Discard)
1014 } else if self.term.equals(c) {
1015 (EndFieldTerm, NfaInputAction::Epsilon)
1016 } else {
1017 (InField, NfaInputAction::CopyToOutput)
1018 }
1019 }
1020 InQuotedField => {
1021 if self.quoting && self.quote == c {
1022 (InDoubleEscapedQuote, NfaInputAction::Discard)
1023 } else if self.quoting && self.escape == Some(c) {
1024 (InEscapedQuote, NfaInputAction::Discard)
1025 } else {
1026 (InQuotedField, NfaInputAction::CopyToOutput)
1027 }
1028 }
1029 InEscapedQuote => (InQuotedField, NfaInputAction::CopyToOutput),
1030 InDoubleEscapedQuote => {
1031 if self.quoting && self.double_quote && self.quote == c {
1032 (InQuotedField, NfaInputAction::CopyToOutput)
1033 } else if self.delimiter == c {
1034 (EndFieldDelim, NfaInputAction::Discard)
1035 } else if self.term.equals(c) {
1036 (EndFieldTerm, NfaInputAction::Epsilon)
1037 } else {
1038 (InField, NfaInputAction::CopyToOutput)
1039 }
1040 }
1041 InComment => {
1042 if b'\n' == c {
1043 (StartRecord, NfaInputAction::Discard)
1044 } else {
1045 (InComment, NfaInputAction::Discard)
1046 }
1047 }
1048 InRecordTerm => {
1049 if self.term.is_crlf() && b'\r' == c {
1050 (CRLF, NfaInputAction::Discard)
1051 } else {
1052 (EndRecord, NfaInputAction::Discard)
1053 }
1054 }
1055 CRLF => {
1056 if b'\n' == c {
1057 (StartRecord, NfaInputAction::Discard)
1058 } else {
1059 (StartRecord, NfaInputAction::Epsilon)
1060 }
1061 }
1062 }
1063 }
1064}
1065
1066const TRANS_CLASSES: usize = 7;
1085const DFA_STATES: usize = 10;
1086const TRANS_SIZE: usize = TRANS_CLASSES * DFA_STATES;
1087
1088const CLASS_SIZE: usize = 256;
1091
1092struct Dfa {
1097 trans: [DfaState; TRANS_SIZE],
1104 has_output: [bool; TRANS_SIZE],
1108 classes: DfaClasses,
1113 in_field: DfaState,
1115 in_quoted: DfaState,
1117 final_field: DfaState,
1120 final_record: DfaState,
1123}
1124
1125impl Dfa {
1126 fn new() -> Dfa {
1127 Dfa {
1128 trans: [DfaState(0); TRANS_SIZE],
1129 has_output: [false; TRANS_SIZE],
1130 classes: DfaClasses::new(),
1131 in_field: DfaState(0),
1132 in_quoted: DfaState(0),
1133 final_field: DfaState(0),
1134 final_record: DfaState(0),
1135 }
1136 }
1137
1138 fn new_state(&self, nfa_state: NfaState) -> DfaState {
1139 let nclasses = self.classes.num_classes() as u8;
1140 let idx = (nfa_state as u8).checked_mul(nclasses).unwrap();
1141 DfaState(idx)
1142 }
1143
1144 fn new_state_final_end(&self) -> DfaState {
1145 self.new_state(NfaState::StartRecord)
1146 }
1147
1148 fn new_state_final_record(&self) -> DfaState {
1149 self.new_state(NfaState::EndRecord)
1150 }
1151
1152 fn get_output(&self, state: DfaState, c: u8) -> (DfaState, bool) {
1153 let cls = self.classes.classes[c as usize];
1154 let idx = state.0 as usize + cls as usize;
1155 (self.trans[idx], self.has_output[idx])
1156 }
1157
1158 fn set(&mut self, from: DfaState, c: u8, to: DfaState, output: bool) {
1159 let cls = self.classes.classes[c as usize];
1160 let idx = from.0 as usize + cls as usize;
1161 self.trans[idx] = to;
1162 self.has_output[idx] = output;
1163 }
1164
1165 fn finish(&mut self) {
1166 self.in_field = self.new_state(NfaState::InField);
1167 self.in_quoted = self.new_state(NfaState::InQuotedField);
1168 self.final_field = self.new_state(NfaState::EndFieldDelim);
1169 self.final_record = self.new_state(NfaState::EndRecord);
1170 }
1171
1172 fn new_read_field_result(
1173 &self,
1174 state: DfaState,
1175 is_final_trans: bool,
1176 inpdone: bool,
1177 outdone: bool,
1178 ) -> ReadFieldResult {
1179 if state >= self.final_record {
1180 ReadFieldResult::Field { record_end: true }
1181 } else if state == self.final_field {
1182 ReadFieldResult::Field { record_end: false }
1183 } else if is_final_trans && state.is_start() {
1184 ReadFieldResult::End
1185 } else {
1186 debug_assert!(state < self.final_field);
1187 if !inpdone && outdone {
1188 ReadFieldResult::OutputFull
1189 } else {
1190 ReadFieldResult::InputEmpty
1191 }
1192 }
1193 }
1194
1195 fn new_read_record_result(
1196 &self,
1197 state: DfaState,
1198 is_final_trans: bool,
1199 inpdone: bool,
1200 outdone: bool,
1201 endsdone: bool,
1202 ) -> ReadRecordResult {
1203 if state >= self.final_record {
1204 ReadRecordResult::Record
1205 } else if is_final_trans && state.is_start() {
1206 ReadRecordResult::End
1207 } else {
1208 debug_assert!(state < self.final_record);
1209 if !inpdone && outdone {
1210 ReadRecordResult::OutputFull
1211 } else if !inpdone && endsdone {
1212 ReadRecordResult::OutputEndsFull
1213 } else {
1214 ReadRecordResult::InputEmpty
1215 }
1216 }
1217 }
1218}
1219
1220struct DfaClasses {
1222 classes: [u8; CLASS_SIZE],
1223 next_class: usize,
1224}
1225
1226impl DfaClasses {
1227 fn new() -> DfaClasses {
1228 DfaClasses { classes: [0; CLASS_SIZE], next_class: 1 }
1229 }
1230
1231 fn add(&mut self, b: u8) {
1232 if self.next_class > CLASS_SIZE {
1233 panic!("added too many classes")
1234 }
1235 self.classes[b as usize] = self.next_class as u8;
1236 self.next_class += 1;
1237 }
1238
1239 fn num_classes(&self) -> usize {
1240 self.next_class
1241 }
1242
1243 #[inline(always)]
1254 fn scan_and_copy(
1255 &self,
1256 input: &[u8],
1257 nin: &mut usize,
1258 output: &mut [u8],
1259 nout: &mut usize,
1260 ) {
1261 while *nin < input.len()
1262 && *nout < output.len()
1263 && self.classes[input[*nin] as usize] == 0
1264 {
1265 output[*nout] = input[*nin];
1266 *nin += 1;
1267 *nout += 1;
1268 }
1269 }
1270}
1271
1272#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
1279struct DfaState(u8);
1280
1281impl DfaState {
1282 fn start() -> DfaState {
1283 DfaState(0)
1284 }
1285
1286 fn is_start(&self) -> bool {
1287 self.0 == 0
1288 }
1289}
1290
1291impl fmt::Debug for Dfa {
1292 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1293 write!(f, "Dfa(N/A)")
1294 }
1295}
1296
1297impl fmt::Debug for DfaClasses {
1298 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1299 write!(
1300 f,
1301 "DfaClasses {{ classes: N/A, next_class: {:?} }}",
1302 self.next_class
1303 )
1304 }
1305}
1306
1307impl Clone for Dfa {
1308 fn clone(&self) -> Dfa {
1309 let mut dfa = Dfa::new();
1310 dfa.trans.copy_from_slice(&self.trans);
1311 dfa
1312 }
1313}
1314
1315impl Clone for DfaClasses {
1316 fn clone(&self) -> DfaClasses {
1317 let mut x = DfaClasses::new();
1318 x.classes.copy_from_slice(&self.classes);
1319 x
1320 }
1321}
1322
1323#[cfg(test)]
1324mod tests {
1325 use core::str;
1326
1327 use arrayvec::{ArrayString, ArrayVec};
1328
1329 use super::{ReadFieldResult, Reader, ReaderBuilder, Terminator};
1330
1331 type Csv = ArrayVec<[Row; 10]>;
1332 type Row = ArrayVec<[Field; 10]>;
1333 type Field = ArrayString<[u8; 10]>;
1334
1335 fn b(s: &str) -> &[u8] {
1337 s.as_bytes()
1338 }
1339
1340 macro_rules! csv {
1341 ($([$($field:expr),*]),*) => {{
1342 #[allow(unused_mut)]
1343 fn x() -> Csv {
1344 let mut csv = Csv::new();
1345 $(
1346 let mut row = Row::new();
1347 $(
1348 row.push(Field::from($field).unwrap());
1349 )*
1350 csv.push(row);
1351 )*
1352 csv
1353 }
1354 x()
1355 }}
1356 }
1357
1358 macro_rules! parses_to {
1359 ($name:ident, $data:expr, $expected:expr) => {
1360 parses_to!($name, $data, $expected, |builder| builder);
1361 };
1362 ($name:ident, $data:expr, $expected:expr, $config:expr) => {
1363 #[test]
1364 fn $name() {
1365 let mut builder = ReaderBuilder::new();
1366 builder.nfa(true);
1367 $config(&mut builder);
1368 let mut rdr = builder.build();
1369 let got = parse_by_field(&mut rdr, $data);
1370 let expected = $expected;
1371 assert_eq!(expected, got, "nfa by field");
1372
1373 let mut builder = ReaderBuilder::new();
1374 builder.nfa(true);
1375 $config(&mut builder);
1376 let mut rdr = builder.build();
1377 let got = parse_by_record(&mut rdr, $data);
1378 let expected = $expected;
1379 assert_eq!(expected, got, "nfa by record");
1380
1381 let mut builder = ReaderBuilder::new();
1382 $config(&mut builder);
1383 let mut rdr = builder.build();
1384 let got = parse_by_field(&mut rdr, $data);
1385 let expected = $expected;
1386 assert_eq!(expected, got, "dfa by field");
1387
1388 let mut builder = ReaderBuilder::new();
1389 $config(&mut builder);
1390 let mut rdr = builder.build();
1391 let got = parse_by_record(&mut rdr, $data);
1392 let expected = $expected;
1393 assert_eq!(expected, got, "dfa by record");
1394 }
1395 };
1396 }
1397
1398 fn parse_by_field(rdr: &mut Reader, data: &str) -> Csv {
1399 let mut data = data.as_bytes();
1400 let mut field = [0u8; 10];
1401 let mut csv = Csv::new();
1402 let mut row = Row::new();
1403 let mut outpos = 0;
1404 loop {
1405 let (res, nin, nout) = rdr.read_field(data, &mut field[outpos..]);
1406 data = &data[nin..];
1407 outpos += nout;
1408
1409 match res {
1410 ReadFieldResult::InputEmpty => {
1411 if !data.is_empty() {
1412 panic!("missing input data")
1413 }
1414 }
1415 ReadFieldResult::OutputFull => panic!("field too large"),
1416 ReadFieldResult::Field { record_end } => {
1417 let s = str::from_utf8(&field[..outpos]).unwrap();
1418 row.push(Field::from(s).unwrap());
1419 outpos = 0;
1420 if record_end {
1421 csv.push(row);
1422 row = Row::new();
1423 }
1424 }
1425 ReadFieldResult::End => {
1426 return csv;
1427 }
1428 }
1429 }
1430 }
1431
1432 fn parse_by_record(rdr: &mut Reader, data: &str) -> Csv {
1433 use crate::ReadRecordResult::*;
1434
1435 let mut data = data.as_bytes();
1436 let mut record = [0; 1024];
1437 let mut ends = [0; 10];
1438
1439 let mut csv = Csv::new();
1440 let (mut outpos, mut endpos) = (0, 0);
1441 loop {
1442 let (res, nin, nout, nend) = rdr.read_record(
1443 data,
1444 &mut record[outpos..],
1445 &mut ends[endpos..],
1446 );
1447 data = &data[nin..];
1448 outpos += nout;
1449 endpos += nend;
1450
1451 match res {
1452 InputEmpty => {
1453 if !data.is_empty() {
1454 panic!("missing input data")
1455 }
1456 }
1457 OutputFull => panic!("record too large (out buffer)"),
1458 OutputEndsFull => panic!("record too large (end buffer)"),
1459 Record => {
1460 let s = str::from_utf8(&record[..outpos]).unwrap();
1461 let mut start = 0;
1462 let mut row = Row::new();
1463 for &end in &ends[..endpos] {
1464 row.push(Field::from(&s[start..end]).unwrap());
1465 start = end;
1466 }
1467 csv.push(row);
1468 outpos = 0;
1469 endpos = 0;
1470 }
1471 End => return csv,
1472 }
1473 }
1474 }
1475
1476 parses_to!(one_row_one_field, "a", csv![["a"]]);
1477 parses_to!(one_row_many_fields, "a,b,c", csv![["a", "b", "c"]]);
1478 parses_to!(one_row_trailing_comma, "a,b,", csv![["a", "b", ""]]);
1479 parses_to!(one_row_one_field_lf, "a\n", csv![["a"]]);
1480 parses_to!(one_row_many_fields_lf, "a,b,c\n", csv![["a", "b", "c"]]);
1481 parses_to!(one_row_trailing_comma_lf, "a,b,\n", csv![["a", "b", ""]]);
1482 parses_to!(one_row_one_field_crlf, "a\r\n", csv![["a"]]);
1483 parses_to!(one_row_many_fields_crlf, "a,b,c\r\n", csv![["a", "b", "c"]]);
1484 parses_to!(one_row_trailing_comma_crlf, "a,b,\r\n", csv![["a", "b", ""]]);
1485 parses_to!(one_row_one_field_cr, "a\r", csv![["a"]]);
1486 parses_to!(one_row_many_fields_cr, "a,b,c\r", csv![["a", "b", "c"]]);
1487 parses_to!(one_row_trailing_comma_cr, "a,b,\r", csv![["a", "b", ""]]);
1488
1489 parses_to!(many_rows_one_field, "a\nb", csv![["a"], ["b"]]);
1490 parses_to!(
1491 many_rows_many_fields,
1492 "a,b,c\nx,y,z",
1493 csv![["a", "b", "c"], ["x", "y", "z"]]
1494 );
1495 parses_to!(
1496 many_rows_trailing_comma,
1497 "a,b,\nx,y,",
1498 csv![["a", "b", ""], ["x", "y", ""]]
1499 );
1500 parses_to!(many_rows_one_field_lf, "a\nb\n", csv![["a"], ["b"]]);
1501 parses_to!(
1502 many_rows_many_fields_lf,
1503 "a,b,c\nx,y,z\n",
1504 csv![["a", "b", "c"], ["x", "y", "z"]]
1505 );
1506 parses_to!(
1507 many_rows_trailing_comma_lf,
1508 "a,b,\nx,y,\n",
1509 csv![["a", "b", ""], ["x", "y", ""]]
1510 );
1511 parses_to!(many_rows_one_field_crlf, "a\r\nb\r\n", csv![["a"], ["b"]]);
1512 parses_to!(
1513 many_rows_many_fields_crlf,
1514 "a,b,c\r\nx,y,z\r\n",
1515 csv![["a", "b", "c"], ["x", "y", "z"]]
1516 );
1517 parses_to!(
1518 many_rows_trailing_comma_crlf,
1519 "a,b,\r\nx,y,\r\n",
1520 csv![["a", "b", ""], ["x", "y", ""]]
1521 );
1522 parses_to!(many_rows_one_field_cr, "a\rb\r", csv![["a"], ["b"]]);
1523 parses_to!(
1524 many_rows_many_fields_cr,
1525 "a,b,c\rx,y,z\r",
1526 csv![["a", "b", "c"], ["x", "y", "z"]]
1527 );
1528 parses_to!(
1529 many_rows_trailing_comma_cr,
1530 "a,b,\rx,y,\r",
1531 csv![["a", "b", ""], ["x", "y", ""]]
1532 );
1533
1534 parses_to!(
1535 trailing_lines_no_record,
1536 "\n\n\na,b,c\nx,y,z\n\n\n",
1537 csv![["a", "b", "c"], ["x", "y", "z"]]
1538 );
1539 parses_to!(
1540 trailing_lines_no_record_cr,
1541 "\r\r\ra,b,c\rx,y,z\r\r\r",
1542 csv![["a", "b", "c"], ["x", "y", "z"]]
1543 );
1544 parses_to!(
1545 trailing_lines_no_record_crlf,
1546 "\r\n\r\n\r\na,b,c\r\nx,y,z\r\n\r\n\r\n",
1547 csv![["a", "b", "c"], ["x", "y", "z"]]
1548 );
1549
1550 parses_to!(empty, "", csv![]);
1551 parses_to!(empty_lines, "\n\n\n\n", csv![]);
1552 parses_to!(
1553 empty_lines_interspersed,
1554 "\n\na,b\n\n\nx,y\n\n\nm,n\n",
1555 csv![["a", "b"], ["x", "y"], ["m", "n"]]
1556 );
1557 parses_to!(empty_lines_crlf, "\r\n\r\n\r\n\r\n", csv![]);
1558 parses_to!(
1559 empty_lines_interspersed_crlf,
1560 "\r\n\r\na,b\r\n\r\n\r\nx,y\r\n\r\n\r\nm,n\r\n",
1561 csv![["a", "b"], ["x", "y"], ["m", "n"]]
1562 );
1563 parses_to!(empty_lines_mixed, "\r\n\n\r\n\n", csv![]);
1564 parses_to!(
1565 empty_lines_interspersed_mixed,
1566 "\n\r\na,b\r\n\n\r\nx,y\r\n\n\r\nm,n\r\n",
1567 csv![["a", "b"], ["x", "y"], ["m", "n"]]
1568 );
1569 parses_to!(empty_lines_cr, "\r\r\r\r", csv![]);
1570 parses_to!(
1571 empty_lines_interspersed_cr,
1572 "\r\ra,b\r\r\rx,y\r\r\rm,n\r",
1573 csv![["a", "b"], ["x", "y"], ["m", "n"]]
1574 );
1575
1576 parses_to!(
1577 term_weird,
1578 "zza,bzc,dzz",
1579 csv![["a", "b"], ["c", "d"]],
1580 |b: &mut ReaderBuilder| {
1581 b.terminator(Terminator::Any(b'z'));
1582 }
1583 );
1584
1585 parses_to!(
1586 ascii_delimited,
1587 "a\x1fb\x1ec\x1fd",
1588 csv![["a", "b"], ["c", "d"]],
1589 |b: &mut ReaderBuilder| {
1590 b.ascii();
1591 }
1592 );
1593
1594 parses_to!(bom_at_start, "\u{feff}a", csv![["a"]]);
1595 parses_to!(bom_in_field, "a\u{feff}", csv![["a\u{feff}"]]);
1596 parses_to!(bom_at_field_start, "a,\u{feff}b", csv![["a", "\u{feff}b"]]);
1597
1598 parses_to!(quote_empty, "\"\"", csv![[""]]);
1599 parses_to!(quote_lf, "\"\"\n", csv![[""]]);
1600 parses_to!(quote_space, "\" \"", csv![[" "]]);
1601 parses_to!(quote_inner_space, "\" a \"", csv![[" a "]]);
1602 parses_to!(quote_outer_space, " \"a\" ", csv![[" \"a\" "]]);
1603
1604 parses_to!(quote_change, "zaz", csv![["a"]], |b: &mut ReaderBuilder| {
1605 b.quote(b'z');
1606 });
1607
1608 parses_to!(
1611 quote_delimiter,
1612 ",a,,b",
1613 csv![["a,b"]],
1614 |b: &mut ReaderBuilder| {
1615 b.quote(b',');
1616 }
1617 );
1618
1619 parses_to!(quote_no_escapes, r#""a\"b""#, csv![[r#"a\b""#]]);
1620 parses_to!(
1621 quote_escapes_no_double,
1622 r#""a""b""#,
1623 csv![[r#"a"b""#]],
1624 |b: &mut ReaderBuilder| {
1625 b.double_quote(false);
1626 }
1627 );
1628 parses_to!(
1629 quote_escapes,
1630 r#""a\"b""#,
1631 csv![[r#"a"b"#]],
1632 |b: &mut ReaderBuilder| {
1633 b.escape(Some(b'\\'));
1634 }
1635 );
1636 parses_to!(
1637 quote_escapes_change,
1638 r#""az"b""#,
1639 csv![[r#"a"b"#]],
1640 |b: &mut ReaderBuilder| {
1641 b.escape(Some(b'z'));
1642 }
1643 );
1644
1645 parses_to!(
1646 quote_escapes_with_comma,
1647 r#""\"A,B\"""#,
1648 csv![[r#""A,B""#]],
1649 |b: &mut ReaderBuilder| {
1650 b.escape(Some(b'\\')).double_quote(false);
1651 }
1652 );
1653
1654 parses_to!(
1655 quoting_disabled,
1656 r#""abc,foo""#,
1657 csv![[r#""abc"#, r#"foo""#]],
1658 |b: &mut ReaderBuilder| {
1659 b.quoting(false);
1660 }
1661 );
1662
1663 parses_to!(
1664 delimiter_tabs,
1665 "a\tb",
1666 csv![["a", "b"]],
1667 |b: &mut ReaderBuilder| {
1668 b.delimiter(b'\t');
1669 }
1670 );
1671 parses_to!(
1672 delimiter_weird,
1673 "azb",
1674 csv![["a", "b"]],
1675 |b: &mut ReaderBuilder| {
1676 b.delimiter(b'z');
1677 }
1678 );
1679
1680 parses_to!(extra_record_crlf_1, "foo\n1\n", csv![["foo"], ["1"]]);
1681 parses_to!(extra_record_crlf_2, "foo\r\n1\r\n", csv![["foo"], ["1"]]);
1682
1683 parses_to!(
1684 comment_1,
1685 "foo\n# hi\nbar\n",
1686 csv![["foo"], ["bar"]],
1687 |b: &mut ReaderBuilder| {
1688 b.comment(Some(b'#'));
1689 }
1690 );
1691 parses_to!(
1692 comment_2,
1693 "foo\n # hi\nbar\n",
1694 csv![["foo"], [" # hi"], ["bar"]],
1695 |b: &mut ReaderBuilder| {
1696 b.comment(Some(b'#'));
1697 }
1698 );
1699 parses_to!(
1700 comment_3,
1701 "foo\n# hi\nbar\n",
1702 csv![["foo"], ["# hi"], ["bar"]],
1703 |b: &mut ReaderBuilder| {
1704 b.comment(Some(b'\n'));
1705 }
1706 );
1707 parses_to!(
1708 comment_4,
1709 "foo,b#ar,baz",
1710 csv![["foo", "b#ar", "baz"]],
1711 |b: &mut ReaderBuilder| {
1712 b.comment(Some(b'#'));
1713 }
1714 );
1715 parses_to!(
1716 comment_5,
1717 "foo,#bar,baz",
1718 csv![["foo", "#bar", "baz"]],
1719 |b: &mut ReaderBuilder| {
1720 b.comment(Some(b'#'));
1721 }
1722 );
1723
1724 macro_rules! assert_read {
1725 (
1726 $rdr:expr, $input:expr, $output:expr,
1727 $expect_in:expr, $expect_out:expr, $expect_res:expr
1728 ) => {{
1729 let (res, nin, nout) = $rdr.read_field($input, $output);
1730 assert_eq!($expect_in, nin);
1731 assert_eq!($expect_out, nout);
1732 assert_eq!($expect_res, res);
1733 }};
1734 }
1735
1736 #[test]
1739 fn stream_empty() {
1740 use crate::ReadFieldResult::*;
1741
1742 let mut rdr = Reader::new();
1743 assert_read!(rdr, &[], &mut [], 0, 0, End);
1744 }
1745
1746 #[test]
1748 fn stream_space() {
1749 use crate::ReadFieldResult::*;
1750
1751 let mut rdr = Reader::new();
1752 assert_read!(rdr, b(" "), &mut [0], 1, 1, InputEmpty);
1753 assert_read!(rdr, &[], &mut [0], 0, 0, Field { record_end: true });
1754 assert_read!(rdr, &[], &mut [0], 0, 0, End);
1755 }
1756
1757 #[test]
1759 fn stream_comma() {
1760 use crate::ReadFieldResult::*;
1761
1762 let mut rdr = Reader::new();
1763 assert_read!(rdr, b(","), &mut [0], 1, 0, Field { record_end: false });
1764 assert_read!(rdr, &[], &mut [0], 0, 0, Field { record_end: true });
1765 assert_read!(rdr, &[], &mut [0], 0, 0, End);
1766 }
1767
1768 #[test]
1771 fn stream_output_chunks() {
1772 use crate::ReadFieldResult::*;
1773
1774 let mut inp = b("fooquux");
1775 let out = &mut [0; 2];
1776 let mut rdr = Reader::new();
1777
1778 assert_read!(rdr, inp, out, 2, 2, OutputFull);
1779 assert_eq!(out, b("fo"));
1780 inp = &inp[2..];
1781
1782 assert_read!(rdr, inp, out, 2, 2, OutputFull);
1783 assert_eq!(out, b("oq"));
1784 inp = &inp[2..];
1785
1786 assert_read!(rdr, inp, out, 2, 2, OutputFull);
1787 assert_eq!(out, b("uu"));
1788 inp = &inp[2..];
1789
1790 assert_read!(rdr, inp, out, 1, 1, InputEmpty);
1791 assert_eq!(&out[..1], b("x"));
1792 inp = &inp[1..];
1793 assert!(inp.is_empty());
1794
1795 assert_read!(rdr, &[], out, 0, 0, Field { record_end: true });
1796 assert_read!(rdr, inp, out, 0, 0, End);
1797 }
1798
1799 #[test]
1802 fn stream_input_chunks() {
1803 use crate::ReadFieldResult::*;
1804
1805 let out = &mut [0; 10];
1806 let mut rdr = Reader::new();
1807
1808 assert_read!(rdr, b("fo"), out, 2, 2, InputEmpty);
1809 assert_eq!(&out[..2], b("fo"));
1810
1811 assert_read!(rdr, b("oq"), &mut out[2..], 2, 2, InputEmpty);
1812 assert_eq!(&out[..4], b("fooq"));
1813
1814 assert_read!(rdr, b("uu"), &mut out[4..], 2, 2, InputEmpty);
1815 assert_eq!(&out[..6], b("fooquu"));
1816
1817 assert_read!(rdr, b("x"), &mut out[6..], 1, 1, InputEmpty);
1818 assert_eq!(&out[..7], b("fooquux"));
1819
1820 assert_read!(rdr, &[], out, 0, 0, Field { record_end: true });
1821 assert_read!(rdr, &[], out, 0, 0, End);
1822 }
1823
1824 #[test]
1826 fn stream_doubled_quotes() {
1827 use crate::ReadFieldResult::*;
1828
1829 let out = &mut [0; 10];
1830 let mut rdr = Reader::new();
1831
1832 assert_read!(rdr, b("\"fo\""), out, 4, 2, InputEmpty);
1833 assert_eq!(&out[..2], b("fo"));
1834
1835 assert_read!(rdr, b("\"o"), &mut out[2..], 2, 2, InputEmpty);
1836 assert_eq!(&out[..4], b("fo\"o"));
1837
1838 assert_read!(rdr, &[], out, 0, 0, Field { record_end: true });
1839 assert_read!(rdr, &[], out, 0, 0, End);
1840 }
1841
1842 #[test]
1844 fn stream_escaped_quotes() {
1845 use crate::ReadFieldResult::*;
1846
1847 let out = &mut [0; 10];
1848 let mut builder = ReaderBuilder::new();
1849 let mut rdr = builder.escape(Some(b'\\')).build();
1850
1851 assert_read!(rdr, b("\"fo\\"), out, 4, 2, InputEmpty);
1852 assert_eq!(&out[..2], b("fo"));
1853
1854 assert_read!(rdr, b("\"o"), &mut out[2..], 2, 2, InputEmpty);
1855 assert_eq!(&out[..4], b("fo\"o"));
1856
1857 assert_read!(rdr, &[], out, 0, 0, Field { record_end: true });
1858 assert_read!(rdr, &[], out, 0, 0, End);
1859 }
1860
1861 #[test]
1863 fn stream_empty_output() {
1864 use crate::ReadFieldResult::*;
1865
1866 let out = &mut [0; 10];
1867 let mut rdr = Reader::new();
1868
1869 assert_read!(
1870 rdr,
1871 b("foo,bar"),
1872 out,
1873 4,
1874 3,
1875 Field { record_end: false }
1876 );
1877 assert_eq!(&out[..3], b("foo"));
1878
1879 assert_read!(rdr, b("bar"), &mut [], 0, 0, OutputFull);
1880
1881 assert_read!(rdr, b("bar"), out, 3, 3, InputEmpty);
1882 assert_eq!(&out[..3], b("bar"));
1883
1884 assert_read!(rdr, &[], out, 0, 0, Field { record_end: true });
1885 assert_read!(rdr, &[], out, 0, 0, End);
1886 }
1887
1888 #[test]
1891 fn reset_works() {
1892 use crate::ReadFieldResult::*;
1893
1894 let out = &mut [0; 10];
1895 let mut rdr = Reader::new();
1896
1897 assert_read!(rdr, b("\"foo"), out, 4, 3, InputEmpty);
1898 assert_eq!(&out[..3], b("foo"));
1899
1900 rdr.reset();
1908
1909 assert_read!(rdr, b("\"\"bar\""), out, 6, 4, InputEmpty);
1910 assert_eq!(&out[..4], b("bar\""));
1911 }
1912
1913 #[test]
1915 fn line_numbers() {
1916 use crate::ReadFieldResult::*;
1917
1918 let out = &mut [0; 10];
1919 let mut rdr = Reader::new();
1920
1921 assert_eq!(1, rdr.line());
1922
1923 assert_read!(rdr, b("\n\n\n\n"), out, 4, 0, InputEmpty);
1924 assert_eq!(5, rdr.line());
1925
1926 assert_read!(rdr, b("foo,"), out, 4, 3, Field { record_end: false });
1927 assert_eq!(5, rdr.line());
1928
1929 assert_read!(rdr, b("bar\n"), out, 4, 3, Field { record_end: true });
1930 assert_eq!(6, rdr.line());
1931
1932 assert_read!(rdr, &[], &mut [0], 0, 0, End);
1933 assert_eq!(6, rdr.line());
1934 }
1935
1936 macro_rules! assert_read_record {
1937 (
1938 $rdr:expr, $input:expr, $output:expr, $ends:expr,
1939 $expect_in:expr, $expect_out:expr,
1940 $expect_end:expr, $expect_res:expr
1941 ) => {{
1942 let (res, nin, nout, nend) =
1943 $rdr.read_record($input, $output, $ends);
1944 assert_eq!($expect_res, res, "result");
1945 assert_eq!($expect_in, nin, "input");
1946 assert_eq!($expect_out, nout, "output");
1947 assert_eq!($expect_end, nend, "ends");
1948 }};
1949 }
1950
1951 #[test]
1953 fn stream_record() {
1954 use crate::ReadRecordResult::*;
1955
1956 let mut inp = b("foo,bar\nbaz");
1957 let out = &mut [0; 1024];
1958 let ends = &mut [0; 10];
1959 let mut rdr = Reader::new();
1960
1961 assert_read_record!(rdr, &inp, out, ends, 8, 6, 2, Record);
1962 assert_eq!(ends[0], 3);
1963 assert_eq!(ends[1], 6);
1964 inp = &inp[8..];
1965
1966 assert_read_record!(rdr, &inp, out, ends, 3, 3, 0, InputEmpty);
1967 inp = &inp[3..];
1968
1969 assert_read_record!(rdr, &inp, out, ends, 0, 0, 1, Record);
1970 assert_eq!(ends[0], 3);
1971
1972 assert_read_record!(rdr, &inp, out, ends, 0, 0, 0, End);
1973 }
1974
1975 #[test]
1978 fn stream_record_last_end_output_full() {
1979 use crate::ReadRecordResult::*;
1980
1981 let mut inp = b("foo,bar\nbaz");
1982 let out = &mut [0; 1024];
1983 let ends = &mut [0; 10];
1984 let mut rdr = Reader::new();
1985
1986 assert_read_record!(rdr, &inp, out, ends, 8, 6, 2, Record);
1987 assert_eq!(ends[0], 3);
1988 assert_eq!(ends[1], 6);
1989 inp = &inp[8..];
1990
1991 assert_read_record!(rdr, &inp, out, ends, 3, 3, 0, InputEmpty);
1992 inp = &inp[3..];
1993
1994 assert_read_record!(rdr, &inp, out, &mut [], 0, 0, 0, OutputEndsFull);
1995 assert_read_record!(rdr, &inp, out, ends, 0, 0, 1, Record);
1996 assert_eq!(ends[0], 3);
1997
1998 assert_read_record!(rdr, &inp, out, ends, 0, 0, 0, End);
1999 }
2000
2001 #[test]
2002 fn reset_input_partial() {
2003 use crate::ReadRecordResult::*;
2004
2005 let inp = b("foo,bar\nbaz");
2006 let out = &mut [0; 1024];
2007 let ends = &mut [0; 10];
2008 let mut rdr = Reader::new();
2009
2010 assert_read_record!(rdr, &inp, out, ends, 8, 6, 2, Record);
2011
2012 let (result, _, _, _) = rdr.read_record(&inp[8..], out, ends);
2014 assert_eq!(result, InputEmpty);
2015
2016 rdr.reset();
2017
2018 let inp = b("baz,raz\n");
2019 let (result, _, _, _) = rdr.read_record(inp, out, ends);
2020 assert_eq!(result, Record);
2021 assert_eq!(ends[0], 3);
2022 }
2023}