use std::path::{Path, PathBuf};
use std::sync::OnceLock;
use crate::file::{FileEntry, FileIcon, FileVersionInfo, Priority, Result};
use crate::win::resolve_appexec_link;
#[derive(Debug)]
pub struct ReparsePoint {
link_path: PathBuf,
target_path: PathBuf,
display_name: OnceLock<String>,
}
impl ReparsePoint {
#[must_use]
pub fn new(link_path: PathBuf) -> Option<Self> {
let target_path = resolve_appexec_link(&link_path)?;
Some(Self {
link_path,
target_path,
display_name: OnceLock::new(),
})
}
}
impl FileEntry for ReparsePoint {
fn path(&self) -> &Path {
&self.target_path
}
fn link_path(&self) -> Option<&Path> {
Some(&self.link_path)
}
fn icon(&self) -> Result<FileIcon> {
Ok(FileIcon::from_paths(self.target_path.clone(), None))
}
fn version_info(&self) -> Result<FileVersionInfo> {
Ok(FileVersionInfo::load(&self.target_path)?)
}
fn priority(&self) -> Priority {
Priority(1.0)
}
fn display_name(&self) -> String {
self.display_name
.get_or_init(|| self.compute_display_name())
.clone()
}
}
impl ReparsePoint {
fn compute_display_name(&self) -> String {
self.version_info()
.ok()
.and_then(|info| {
info.english()
.and_then(|fi| fi.meaningful_product_name().map(String::from))
})
.or_else(|| {
self.target_path
.file_stem()
.map(|s| s.to_string_lossy().into_owned())
})
.unwrap_or_default()
}
}