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