sws_lua/
writer.rs

1use std::io;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Deserialize, Serialize)]
6pub struct CsvWriterConfig {
7    #[serde(default = "default_csv_delimiter")]
8    pub delimiter: char,
9    #[serde(default)]
10    pub escape: Option<char>,
11    #[serde(default)]
12    pub flexible: bool,
13    #[serde(default = "default_csv_terminator")]
14    pub terminator: CsvTerminator,
15}
16
17impl Default for CsvWriterConfig {
18    fn default() -> Self {
19        Self {
20            delimiter: default_csv_delimiter(),
21            escape: None,
22            flexible: false,
23            terminator: default_csv_terminator(),
24        }
25    }
26}
27
28fn default_csv_delimiter() -> char {
29    ','
30}
31
32fn default_csv_terminator() -> CsvTerminator {
33    CsvTerminator::Any('\n')
34}
35
36#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
37pub enum CsvTerminator {
38    CRLF,
39    Any(char),
40}
41
42impl From<CsvTerminator> for csv::Terminator {
43    fn from(source: CsvTerminator) -> Self {
44        match source {
45            CsvTerminator::CRLF => Self::CRLF,
46            CsvTerminator::Any(c) => Self::Any(c as u8),
47        }
48    }
49}
50
51impl From<&CsvWriterConfig> for csv::WriterBuilder {
52    fn from(c: &CsvWriterConfig) -> Self {
53        let mut builder = csv::WriterBuilder::new();
54        builder.delimiter(c.delimiter as u8);
55        builder.terminator(c.terminator.into());
56        builder.flexible(c.flexible);
57        if let Some(escape) = c.escape {
58            builder.double_quote(false);
59            builder.escape(escape as u8);
60        } else {
61            builder.double_quote(true);
62        }
63        builder
64    }
65}
66
67pub enum CsvWriter {
68    File(csv::Writer<fs_err::File>),
69    Stdout(csv::Writer<io::Stdout>),
70}
71
72impl CsvWriter {
73    pub fn flush(&mut self) -> io::Result<()> {
74        match self {
75            Self::File(wtr) => wtr.flush(),
76            Self::Stdout(wtr) => wtr.flush(),
77        }
78    }
79
80    pub fn write_record<I, T>(&mut self, record: I) -> csv::Result<()>
81    where
82        I: IntoIterator<Item = T>,
83        T: AsRef<[u8]>,
84    {
85        match self {
86            Self::File(wtr) => wtr.write_record(record),
87            Self::Stdout(wtr) => wtr.write_record(record),
88        }
89    }
90}
91
92#[derive(Debug, Clone, Deserialize, Serialize)]
93pub enum FileMode {
94    Create,
95    Append,
96    Truncate,
97}
98
99impl Default for FileMode {
100    fn default() -> Self {
101        Self::Create
102    }
103}
104
105impl From<FileMode> for fs_err::OpenOptions {
106    fn from(mode: FileMode) -> Self {
107        let mut opts = fs_err::OpenOptions::new();
108        opts.write(true);
109        match mode {
110            FileMode::Create => opts.create_new(true),
111            FileMode::Append => opts.create(true).append(true),
112            FileMode::Truncate => opts.create(true).truncate(true),
113        };
114        opts
115    }
116}