Skip to main content

csv_basic/
basic.rs

1//! Read and write CSV with `reliakit-csv`, including a typed record.
2//!
3//! Run with: `cargo run -p reliakit-csv --example csv_basic`
4
5use reliakit_csv::{
6    from_csv_str, read_str, to_csv_string, CsvDecode, CsvDecodeError, CsvEncode, CsvField,
7    CsvWriter,
8};
9
10#[derive(Debug, PartialEq)]
11struct Service {
12    name: String,
13    port: u16,
14    enabled: bool,
15}
16
17impl CsvEncode for Service {
18    fn header() -> Vec<&'static str> {
19        vec!["name", "port", "enabled"]
20    }
21
22    fn encode_fields(&self, out: &mut Vec<String>) {
23        out.push(self.name.encode_field());
24        out.push(self.port.encode_field());
25        out.push(self.enabled.encode_field());
26    }
27}
28
29impl CsvDecode for Service {
30    fn decode_fields(fields: &[&str]) -> Result<Self, CsvDecodeError> {
31        if fields.len() != 3 {
32            return Err(CsvDecodeError::field_count());
33        }
34        Ok(Service {
35            name: String::decode_field(fields[0]).map_err(|e| e.at_field(0))?,
36            port: u16::decode_field(fields[1]).map_err(|e| e.at_field(1))?,
37            enabled: bool::decode_field(fields[2]).map_err(|e| e.at_field(2))?,
38        })
39    }
40}
41
42fn main() {
43    // Low-level: parse rows of strings.
44    let rows = read_str("a,b\n1,2\n").unwrap();
45    println!("rows: {rows:?}");
46
47    // Low-level: write rows deterministically (a field is quoted only if needed).
48    let mut writer = CsvWriter::new();
49    writer.write_record(["plain", "needs,quote"]);
50    print!("written: {}", writer.into_string());
51
52    // Typed: round-trip a slice of records through a header + rows.
53    let services = vec![
54        Service {
55            name: "api".into(),
56            port: 8080,
57            enabled: true,
58        },
59        Service {
60            name: "worker, west".into(),
61            port: 9000,
62            enabled: false,
63        },
64    ];
65    let text = to_csv_string(&services);
66    print!("encoded:\n{text}");
67
68    let decoded: Vec<Service> = from_csv_str(&text).unwrap();
69    assert_eq!(decoded, services);
70    println!("round-trip ok: {} record(s)", decoded.len());
71}