oca_data_entry/format/
csv.rs1use std::io::Write;
2
3use crate::model::EntrySchema;
4
5pub struct CsvOptions {
6 pub include_metadata_row: bool,
7 pub label_lang: Option<String>,
8 pub metadata_lang: Option<String>,
9}
10
11pub fn write_csv(
12 schema: &EntrySchema,
13 mut out: impl Write,
14 opts: &CsvOptions,
15) -> std::io::Result<()> {
16 writeln!(out, "# oca_bundle_said={}", schema.said)?;
18
19 let headers: Vec<String> = schema
21 .attributes
22 .iter()
23 .map(|a| {
24 if opts.label_lang.is_some() {
25 a.label.clone().unwrap_or_else(|| a.name.clone())
26 } else {
27 a.name.clone()
28 }
29 })
30 .collect();
31
32 writeln!(out, "{}", headers.join(","))?;
33
34 if opts.include_metadata_row {
36 let meta: Vec<String> = schema
37 .attributes
38 .iter()
39 .map(|a| {
40 let mut parts = Vec::new();
41 if a.required {
42 parts.push("required".to_string());
43 }
44 if let Some(t) = &a.attr_type {
45 parts.push(format!("type={}", t));
46 }
47 if let Some(f) = &a.format {
48 parts.push(format!("format={}", f));
49 }
50 if let Some(u) = &a.unit {
51 parts.push(format!("unit={}", u));
52 }
53 if let Some(c) = &a.cardinality {
54 parts.push(format!("cardinality={}", c));
55 }
56 if let Some(values) = &a.entry_values {
57 parts.push(format!("values={}", values.join("|")));
58 }
59 parts.join("; ")
60 })
61 .collect();
62 writeln!(out, "{}", meta.join(","))?;
63 }
64
65 Ok(())
66}