create structs for list entries

This commit is contained in:
yggverse 2025-06-25 10:31:48 +03:00
parent a238d0cd44
commit 5f0918a06c

View file

@ -3,7 +3,13 @@ mod list_config;
use crate::response::Response; use crate::response::Response;
use anyhow::{Result, bail}; use anyhow::{Result, bail};
use list_config::ListConfig; use list_config::ListConfig;
use std::{fs, io::Read, os::unix::fs::MetadataExt, path::PathBuf, str::FromStr}; use std::{
fs::{self, Metadata},
io::Read,
os::unix::fs::MetadataExt,
path::PathBuf,
str::FromStr,
};
/// In-session disk storage API /// In-session disk storage API
pub struct Storage { pub struct Storage {
@ -100,47 +106,62 @@ impl Storage {
format!("{:.2} GB", f / GB) format!("{:.2} GB", f / GB)
} }
} }
/// Formatted directory entry
struct Dir {
/// Items quantity in this directory
count: usize,
meta: Metadata,
name: String,
}
/// Formatted file entry
struct File {
meta: Metadata,
name: String,
}
// separate dirs from files, to show the dirs first // separate dirs from files, to show the dirs first
const C: usize = 25; // @TODO optional const C: usize = 25; // @TODO optional
let mut d = Vec::with_capacity(C); let mut dirs = Vec::with_capacity(C);
let mut f = Vec::with_capacity(C); let mut files = Vec::with_capacity(C);
for entry in fs::read_dir(path)? { for entry in fs::read_dir(path)? {
let e = entry?; let e = entry?;
let m = fs::metadata(e.path())?; let meta = fs::metadata(e.path())?;
match (m.is_dir(), m.is_file()) { match (meta.is_dir(), meta.is_file()) {
(true, _) => d.push(( (true, _) => dirs.push(Dir {
e.file_name().to_string_lossy().to_string(), meta,
m, name: e.file_name().to_string_lossy().to_string(),
fs::read_dir(e.path()).map_or(0, |i| i.count()), count: fs::read_dir(e.path()).map_or(0, |i| i.count()),
)), }),
(_, true) => f.push((e.file_name().to_string_lossy().to_string(), m)), (_, true) => files.push(File {
meta,
name: e.file_name().to_string_lossy().to_string(),
}),
_ => {} // @TODO symlinks support? _ => {} // @TODO symlinks support?
} }
} }
// build resulting list // build resulting list
let mut r = Vec::with_capacity(d.len() + f.len()); let mut r = Vec::with_capacity(dirs.len() + files.len());
// append top navigation (if not root) // append top navigation (if not root)
if &self.public_dir != path { if &self.public_dir != path {
r.push("=> ../".to_string()) r.push("=> ../".to_string())
} }
// format dirs list // format dirs list
d.sort_by(|(a, _, _), (b, _, _)| a.cmp(b)); dirs.sort_by(|a, b| a.name.cmp(&b.name));
for (n, m, c) in d { for dir in dirs {
r.push({ r.push({
let mut l = format!("=> {}/", encode(&n)); let dc = &self.list_config.dir; // just short alias
let mut l = format!("=> {}/", encode(&dir.name));
let mut a = Vec::new(); let mut a = Vec::new();
if self.list_config.dir.is_count { if dc.is_count {
a.push(c.to_string()); a.push(dir.count.to_string());
} }
if self.list_config.dir.time.is_accessed { if dc.time.is_accessed {
a.push(self.t(m.atime())) a.push(self.t(dir.meta.atime()))
} }
if self.list_config.dir.time.is_created { if dc.time.is_created {
a.push(self.t(m.ctime())) a.push(self.t(dir.meta.ctime()))
} }
if self.list_config.dir.time.is_modified { if dc.time.is_modified {
a.push(self.t(m.mtime())) a.push(self.t(dir.meta.mtime()))
} }
// @TODO modified, accessed, created etc. // @TODO modified, accessed, created etc.
if !a.is_empty() { if !a.is_empty() {
@ -150,22 +171,23 @@ impl Storage {
}) })
} }
// format files list // format files list
f.sort_by(|(a, _), (b, _)| a.cmp(b)); files.sort_by(|a, b| a.name.cmp(&b.name));
for (n, m) in f { for file in files {
r.push({ r.push({
let mut l = format!("=> {}", encode(&n)); let fc = &self.list_config.file; // just short alias
let mut l = format!("=> {}", encode(&file.name));
let mut a = Vec::new(); let mut a = Vec::new();
if self.list_config.file.is_size { if fc.is_size {
a.push(b(m.size())) a.push(b(file.meta.size()))
} }
if self.list_config.file.time.is_accessed { if fc.time.is_accessed {
a.push(self.t(m.atime())) a.push(self.t(file.meta.atime()))
} }
if self.list_config.file.time.is_created { if fc.time.is_created {
a.push(self.t(m.ctime())) a.push(self.t(file.meta.ctime()))
} }
if self.list_config.file.time.is_modified { if fc.time.is_modified {
a.push(self.t(m.mtime())) a.push(self.t(file.meta.mtime()))
} }
if !a.is_empty() { if !a.is_empty() {
l.push_str(&format!(" ({})", a.join(","))); l.push_str(&format!(" ({})", a.join(",")));