Skip to main content

ravenrs_core/
csv.rs

1//! CSV fields (RFC 4180), written the same way by every engine that exports CSV.
2
3/// Appends `text` as one field, quoted when it holds `separator`, a quote or a line break.
4///
5/// ```
6/// let mut line = String::new();
7/// ravenrs_core::csv::push_field(&mut line, "Smith, \"J\"", ',');
8/// assert_eq!(line, "\"Smith, \"\"J\"\"\"");
9/// ```
10pub fn push_field(out: &mut String, text: &str, separator: char) {
11    if text.contains([separator, '"', '\n', '\r']) {
12        out.push('"');
13        out.push_str(&text.replace('"', "\"\""));
14        out.push('"');
15    } else {
16        out.push_str(text);
17    }
18}
19
20#[cfg(test)]
21mod tests {
22    use super::push_field;
23
24    fn field(text: &str, separator: char) -> String {
25        let mut out = String::new();
26        push_field(&mut out, text, separator);
27        out
28    }
29
30    #[test]
31    fn quotes_only_what_needs_it() {
32        assert_eq!(field("plain", ','), "plain");
33        assert_eq!(field("a,b", ','), "\"a,b\"");
34        assert_eq!(field("a,b", ';'), "a,b");
35        assert_eq!(field("a;b", ';'), "\"a;b\"");
36        assert_eq!(field("line\nbreak", ','), "\"line\nbreak\"");
37        assert_eq!(field("cr\r", ','), "\"cr\r\"");
38        assert_eq!(field("say \"hi\"", ','), "\"say \"\"hi\"\"\"");
39        assert_eq!(field("", ','), "");
40    }
41}