1use f00_core::Entry;
2use serde::Serialize;
3
4use crate::perms::format_permissions;
5
6#[derive(Serialize)]
7struct JsonEntry<'a> {
8 name: &'a str,
9 path: String,
10 #[serde(skip_serializing_if = "Option::is_none")]
12 absolute_path: Option<String>,
13 kind: &'static str,
14 size: u64,
15 mode: String,
17 mode_octal: String,
19 permissions: String,
21 readonly: bool,
22 #[serde(skip_serializing_if = "Option::is_none")]
23 modified: Option<String>,
24 #[serde(skip_serializing_if = "Option::is_none")]
25 accessed: Option<String>,
26 #[serde(skip_serializing_if = "Option::is_none")]
27 changed: Option<String>,
28 #[serde(skip_serializing_if = "Option::is_none")]
29 created: Option<String>,
30 inode: u64,
31 nlink: u64,
32 blocks: u64,
34 uid: u32,
35 gid: u32,
36 #[serde(skip_serializing_if = "str::is_empty")]
37 owner: &'a str,
38 #[serde(skip_serializing_if = "str::is_empty")]
39 group: &'a str,
40 #[serde(skip_serializing_if = "str::is_empty")]
41 author: &'a str,
42 #[serde(skip_serializing_if = "Option::is_none")]
43 symlink_target: Option<String>,
44 #[serde(skip_serializing_if = "str::is_empty")]
45 context: &'a str,
46 #[serde(skip_serializing_if = "Option::is_none")]
47 extension: Option<&'a str>,
48 git_status: &'static str,
49 depth: usize,
50}
51
52fn rfc3339(dt: Option<chrono::DateTime<chrono::Local>>) -> Option<String> {
53 dt.map(|d| d.to_rfc3339())
54}
55
56pub fn format_json(entries: &[Entry]) -> Result<String, serde_json::Error> {
58 let items: Vec<JsonEntry<'_>> = entries
59 .iter()
60 .filter(|e| !e.is_dir_header)
61 .map(|e| {
62 let mode = format!("{:o}", e.mode);
63 let absolute_path = std::fs::canonicalize(&e.path)
64 .ok()
65 .map(|p| p.display().to_string());
66 JsonEntry {
67 name: &e.name,
68 path: e.path.display().to_string(),
69 absolute_path,
70 kind: e.kind.as_str(),
71 size: e.size,
72 mode: mode.clone(),
73 mode_octal: mode,
74 permissions: format_permissions(e),
75 readonly: e.readonly,
76 modified: rfc3339(e.modified_datetime()),
77 accessed: rfc3339(e.accessed_datetime()),
78 changed: rfc3339(e.changed_datetime()),
79 created: rfc3339(e.created_datetime()),
80 inode: e.inode,
81 nlink: e.nlink,
82 blocks: e.blocks,
83 uid: e.uid,
84 gid: e.gid,
85 owner: e.owner.as_str(),
86 group: e.group.as_str(),
87 author: e.author.as_str(),
88 symlink_target: e.symlink_target.as_ref().map(|p| p.display().to_string()),
89 context: e.context.as_str(),
90 extension: e.extension(),
91 git_status: e.git_status.as_str(),
92 depth: e.depth,
93 }
94 })
95 .collect();
96
97 serde_json::to_string_pretty(&items)
98}