diff --git a/csv-core/src/lib.rs b/csv-core/src/lib.rs index 1e41cb5..4bf4295 100644 --- a/csv-core/src/lib.rs +++ b/csv-core/src/lib.rs @@ -142,7 +142,7 @@ impl Terminator { } /// The quoting style to use when writing CSV data. -#[derive(Clone, Copy, Debug, Default)] +#[derive(Clone, Copy, Debug, Default, PartialEq)] #[non_exhaustive] pub enum QuoteStyle { /// This puts quotes around every field. Always. diff --git a/csv-core/src/writer.rs b/csv-core/src/writer.rs index 011ab06..bef600d 100644 --- a/csv-core/src/writer.rs +++ b/csv-core/src/writer.rs @@ -246,7 +246,10 @@ impl Writer { /// In particular, it will write closing quotes if necessary. pub fn finish(&mut self, mut output: &mut [u8]) -> (WriteResult, usize) { let mut nout = 0; - if self.state.record_bytes == 0 && self.state.in_field { + if self.state.record_bytes == 0 + && self.state.in_field + && self.style != QuoteStyle::Never + { assert!(!self.state.quoting); let (res, o) = self.write(&[self.quote, self.quote], output); if o == 0 { @@ -368,7 +371,7 @@ impl Writer { mut output: &mut [u8], ) -> (WriteResult, usize) { let mut nout = 0; - if self.state.record_bytes == 0 { + if self.state.record_bytes == 0 && self.style != QuoteStyle::Never { assert!(!self.state.quoting); let (res, o) = self.write(&[self.quote, self.quote], output); if o == 0 { @@ -1075,4 +1078,24 @@ mod tests { ); assert_write!(wtr, finish, &mut out[..], 1, InputEmpty, "\""); } + + #[test] + fn never_quote_empty_field_terminator() { + let mut wtr = + WriterBuilder::new().quote_style(QuoteStyle::Never).build(); + let out = &mut [0; 1024]; + + assert_field!(wtr, b(""), &mut out[..], 0, 0, InputEmpty, ""); + assert_write!(wtr, terminator, &mut out[..], 1, InputEmpty, "\n"); + } + + #[test] + fn never_quote_empty_field_finish() { + let mut wtr = + WriterBuilder::new().quote_style(QuoteStyle::Never).build(); + let out = &mut [0; 1024]; + + assert_field!(wtr, b(""), &mut out[..], 0, 0, InputEmpty, ""); + assert_write!(wtr, finish, &mut out[..], 0, InputEmpty, ""); + } } diff --git a/src/writer.rs b/src/writer.rs index 195e663..5b2082a 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -1223,6 +1223,7 @@ mod tests { }; use super::{Writer, WriterBuilder}; + use crate::QuoteStyle; fn wtr_as_string(wtr: Writer>) -> String { String::from_utf8(wtr.into_inner().unwrap()).unwrap() @@ -1450,4 +1451,15 @@ mod tests { let buf = wtr.into_inner().unwrap(); assert_eq!(String::from_utf8(buf).unwrap(), "\"# comment\",another\n"); } + + #[test] + fn never_quote_empty_field() { + let mut wtr = WriterBuilder::new() + .quote_style(QuoteStyle::Never) + .from_writer(vec![]); + wtr.write_record(["foo"]).unwrap(); + wtr.write_record([""]).unwrap(); + wtr.write_record(["bar,baz"]).unwrap(); + assert_eq!(wtr_as_string(wtr), "foo\n\nbar,baz\n"); + } }