Skip to main content

st/formatters/
csv.rs

1use super::Formatter;
2use crate::scanner::{FileNode, TreeStats};
3use anyhow::Result;
4use chrono::{DateTime, Local};
5use csv::Writer;
6use std::io::Write;
7use std::path::Path;
8
9pub struct CsvFormatter;
10
11impl Default for CsvFormatter {
12    fn default() -> Self {
13        Self::new()
14    }
15}
16
17impl CsvFormatter {
18    pub fn new() -> Self {
19        Self
20    }
21}
22
23impl Formatter for CsvFormatter {
24    fn format(
25        &self,
26        writer: &mut dyn Write,
27        nodes: &[FileNode],
28        _stats: &TreeStats,
29        root_path: &Path,
30    ) -> Result<()> {
31        let mut csv_writer = Writer::from_writer(writer);
32
33        // Write header
34        csv_writer.write_record([
35            "path",
36            "type",
37            "size",
38            "permissions",
39            "uid",
40            "gid",
41            "modified",
42            "depth",
43        ])?;
44
45        // Sort nodes by path
46        let mut sorted_nodes = nodes.to_vec();
47        sorted_nodes.sort_by(|a, b| a.path.cmp(&b.path));
48
49        for node in &sorted_nodes {
50            let rel_path = if node.path == root_path {
51                ".".to_string()
52            } else {
53                node.path
54                    .strip_prefix(root_path)
55                    .unwrap_or(&node.path)
56                    .to_string_lossy()
57                    .to_string()
58            };
59
60            let file_type = if node.is_dir { "d" } else { "f" };
61            let datetime = DateTime::<Local>::from(node.modified);
62
63            csv_writer.write_record(&[
64                rel_path,
65                file_type.to_string(),
66                node.size.to_string(),
67                format!("{:o}", node.permissions),
68                node.uid.to_string(),
69                node.gid.to_string(),
70                datetime.to_rfc3339(),
71                node.depth.to_string(),
72            ])?;
73        }
74
75        csv_writer.flush()?;
76        Ok(())
77    }
78}