use std::path::{Path, PathBuf};
use std::sync::OnceLock;
use crate::file::{FileEntry, FileIcon, FileVersionInfo, Priority, Result};
#[derive(Debug)]
pub struct RegularFile {
path: PathBuf,
display_name: OnceLock<String>,
}
impl RegularFile {
#[must_use]
pub const fn new(path: PathBuf) -> Self {
Self {
path,
display_name: OnceLock::new(),
}
}
}
impl FileEntry for RegularFile {
fn path(&self) -> &Path {
&self.path
}
fn link_path(&self) -> Option<&Path> {
None
}
fn icon(&self) -> Result<FileIcon> {
Ok(FileIcon::new(self.path.clone()))
}
fn version_info(&self) -> Result<FileVersionInfo> {
Ok(FileVersionInfo::load(&self.path)?)
}
fn priority(&self) -> Priority {
if self.is_executable() {
Priority(1.25)
} else {
Priority(1.0)
}
}
fn display_name(&self) -> String {
self.display_name
.get_or_init(|| self.compute_display_name())
.clone()
}
}
impl RegularFile {
fn compute_display_name(&self) -> String {
let ext = self.extension();
if ext.is_some_and(|e| e.eq_ignore_ascii_case("exe")) {
return self
.version_info()
.ok()
.and_then(|info| {
info.english()
.and_then(|fi| fi.meaningful_product_name().map(String::from))
})
.or_else(|| {
self.path
.file_stem()
.map(|s| s.to_string_lossy().into_owned())
})
.unwrap_or_default();
}
let strip_extension = ext.is_some_and(|e| e.eq_ignore_ascii_case("url"));
let part = if strip_extension {
self.path.file_stem()
} else {
self.path.file_name()
};
part.map(|s| s.to_string_lossy().into_owned())
.unwrap_or_default()
}
}