diff --git a/csv-core/src/reader.rs b/csv-core/src/reader.rs index fbb8894..6adef8f 100644 --- a/csv-core/src/reader.rs +++ b/csv-core/src/reader.rs @@ -752,7 +752,10 @@ impl Reader { // parsing a new record, then we should sink into the final state // and never move from there. (pro-tip: the start state doubles as // the final state!) - if state >= self.dfa.final_record || state.is_start() { + if state >= self.dfa.final_record + || state.is_start() + || state == self.dfa.in_comment + { self.dfa.new_state_final_end() } else { self.dfa.new_state_final_record() @@ -1116,6 +1119,8 @@ struct Dfa { in_field: DfaState, /// The DFA state corresponding to being inside an quoted field. in_quoted: DfaState, + /// The DFA state corresponding to being inside a comment. + in_comment: DfaState, /// The minimum DFA state that indicates a field has been parsed. All DFA /// states greater than this are also final-field states. final_field: DfaState, @@ -1132,6 +1137,7 @@ impl Dfa { classes: DfaClasses::new(), in_field: DfaState(0), in_quoted: DfaState(0), + in_comment: DfaState(0), final_field: DfaState(0), final_record: DfaState(0), } @@ -1167,6 +1173,7 @@ impl Dfa { fn finish(&mut self) { self.in_field = self.new_state(NfaState::InField); self.in_quoted = self.new_state(NfaState::InQuotedField); + self.in_comment = self.new_state(NfaState::InComment); self.final_field = self.new_state(NfaState::EndFieldDelim); self.final_record = self.new_state(NfaState::EndRecord); } @@ -1722,6 +1729,23 @@ mod tests { b.comment(Some(b'#')); } ); + // ref: https://github.com/BurntSushi/rust-csv/issues/363 + parses_to!( + comment_at_end_of_file_should_be_ignored1, + "foo,bar,baz\n# this is a comment in last line", + csv![["foo", "bar", "baz"]], + |b: &mut ReaderBuilder| { + b.comment(Some(b'#')); + } + ); + parses_to!( + comment_at_end_of_file_should_be_ignored2, + "foo,bar,baz\n# this is a comment in last line\n", + csv![["foo", "bar", "baz"]], + |b: &mut ReaderBuilder| { + b.comment(Some(b'#')); + } + ); macro_rules! assert_read { (