use std::path::PathBuf;
use std::time::SystemTime;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum EntryKind {
File,
Directory,
Symlink,
Other,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FileEntry {
pub path: PathBuf,
pub relative_path: Option<PathBuf>,
pub kind: EntryKind,
pub size: Option<u64>,
pub modified: Option<SystemTime>,
pub readonly: Option<bool>,
}
impl FileEntry {
pub fn new(path: PathBuf, kind: EntryKind) -> Self {
Self {
path,
relative_path: None,
kind,
size: None,
modified: None,
readonly: None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[non_exhaustive]
pub enum SortMode {
None,
#[default]
Path,
Name,
DirsFirst,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[non_exhaustive]
pub enum TraversalErrorPolicy {
#[default]
FailFast,
SkipErrors,
}
pub fn sort_entries(entries: &mut [FileEntry], mode: SortMode) {
match mode {
SortMode::None => {}
SortMode::Path => {
entries.sort_by(|a, b| a.path.to_string_lossy().cmp(&b.path.to_string_lossy()));
}
SortMode::Name => {
entries.sort_by(|a, b| {
let an = a
.path
.file_name()
.map(|n| n.to_string_lossy())
.unwrap_or_default();
let bn = b
.path
.file_name()
.map(|n| n.to_string_lossy())
.unwrap_or_default();
an.cmp(&bn)
.then_with(|| a.path.to_string_lossy().cmp(&b.path.to_string_lossy()))
});
}
SortMode::DirsFirst => {
entries.sort_by(|a, b| {
let ak = kind_rank(a.kind);
let bk = kind_rank(b.kind);
ak.cmp(&bk)
.then_with(|| a.path.to_string_lossy().cmp(&b.path.to_string_lossy()))
});
}
}
}
fn kind_rank(kind: EntryKind) -> u8 {
match kind {
EntryKind::Directory => 0,
EntryKind::File => 1,
EntryKind::Symlink => 2,
EntryKind::Other => 3,
}
}