use crate::EntryReadError; use std::path::{Path, PathBuf}; #[derive(PartialEq)] pub enum EntryType { File, Directory, } pub struct Entry { pub entry_type: EntryType, pub is_symlink: bool, pub name: String, pub extension: String, pub path: PathBuf, pub original_path: PathBuf, } impl Entry { pub fn from_path>(path: P) -> Result { let path = path.as_ref(); let metadata = path.metadata()?; let canonical_path = std::fs::canonicalize(path)?; let canonical_metadata = canonical_path.metadata()?; let entry_type = if canonical_metadata.is_file() { EntryType::File } else if canonical_metadata.is_dir() { EntryType::Directory } else { return Err(EntryReadError::NotFound); }; let name = match path.file_name() { Some(osstr) => osstr.to_string_lossy().to_string(), None => unreachable!(), }; let extension = match path.extension() { Some(extension) => extension.to_string_lossy().into(), None => String::default(), }; Ok(Entry { entry_type, name, extension, path: canonical_path, original_path: path.to_path_buf(), is_symlink: metadata.is_symlink(), }) } /// Splits the filename on the last period, ignoring any period at the /// start of the filename. If no extension is found, the extension is empty. pub fn split_name(&self) -> (String, String) { match self.name.rsplit_once(".") { Some(("", _)) | None => (self.name.to_string(), String::new()), Some((prefix, extension)) => (prefix.to_string(), extension.to_string()), } } pub fn is_file(&self) -> bool { match self.entry_type { EntryType::File => true, _ => false, } } pub fn is_directory(&self) -> bool { match self.entry_type { EntryType::Directory => true, _ => false, } } pub fn read_as_bytes(&self) -> Result, EntryReadError> { return Ok(std::fs::read(&self.path)?); } pub fn read_as_utf8_string(&self) -> Result { return Ok(String::from_utf8_lossy(&self.read_as_bytes()?).to_string()); } } impl AsRef for Entry { fn as_ref(&self) -> &Path { &self.path } }