diff --git a/src/lib.rs b/src/lib.rs index e982f86..d03da91 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -use std::path::Path; +use std::{fmt::Display, path::Path}; mod provider; @@ -14,37 +14,66 @@ pub struct Icon { pub pixels: Vec, } +/// Represents an error +#[derive(Debug)] +pub enum Error { + /// Retrieving the icon failed + Failed, + /// The path does not exist + PathDoesNotExist, + /// The desired icon size is null + NullIconSize, +} + +impl Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Error::Failed => { + write!(f, "Failed to get icon") + } + Error::PathDoesNotExist => { + write!(f, "Path does not exist") + }, + Error::NullIconSize => { + write!(f, "Null icon size") + } + } + } +} + +impl std::error::Error for Error {} + /// Retrieves the icon for a given file. /// /// # Parameters /// * `path` - A file path for which the icon is to be retrieved. /// * `size` - Desired icon size, must be greater than 0. /// # Returns -/// * `Some(Icon)` - If the icon is successfully retrieved. -/// * `None` - If the icon could not be retrieved. +/// * `Ok(Icon)` - If the icon is successfully retrieved. +/// * `Err(Error)` - If the icon could not be retrieved. /// /// # Example /// ``` /// use file_icon_provider::get_file_icon; /// -/// if let Some(icon) = get_file_icon("path/to/file", 64) { +/// if let Ok(icon) = get_file_icon("path/to/file", 64) { /// println!("Icon dimensions: {}x{}", icon.width, icon.height); /// } else { /// println!("Failed to retrieve the icon."); /// } /// ``` -pub fn get_file_icon<'a>(path: impl AsRef + 'a, size: u16) -> Option { +pub fn get_file_icon(path: impl AsRef, size: u16) -> Result { // For consistency: on MacOS if the path does not exist None is returned // but on Windows a default icon is returned. if !path.as_ref().exists() { - return None; + return Err(Error::PathDoesNotExist); } if size == 0 { - return None; + return Err(Error::NullIconSize); } - implementation::get_file_icon(path, size) + implementation::get_file_icon(path, size).ok_or(Error::Failed) } mod implementation { @@ -279,12 +308,12 @@ mod tests { let program_file_path = std::env::args().next().expect("get program path"); let program_file_path = PathBuf::from(&program_file_path); - assert!(get_file_icon(program_file_path, 32).is_some()); + assert!(get_file_icon(program_file_path, 32).is_ok()); } #[test] fn test_not_existing_file() { - assert!(get_file_icon("NOT EXISTING", 32).is_none()); + assert!(get_file_icon("NOT EXISTING", 32).is_err()); } #[test] @@ -292,6 +321,6 @@ mod tests { let program_file_path = std::env::args().next().expect("get program path"); let program_file_path = PathBuf::from(&program_file_path); - assert!(get_file_icon(program_file_path, 0).is_none()); + assert!(get_file_icon(program_file_path, 0).is_err()); } } diff --git a/src/provider.rs b/src/provider.rs index e458261..4c72f85 100644 --- a/src/provider.rs +++ b/src/provider.rs @@ -8,7 +8,7 @@ use std::{ path::Path, }; -use crate::{get_file_icon, Icon}; +use crate::{get_file_icon, Error, Icon}; /// This provider caches icons retrieved using [get_file_icon] /// into a dictionary where keys are file extensions. @@ -40,14 +40,14 @@ impl FileIconProvider { } /// Retrieves the icon for a given file. - pub fn icon(&self, path: impl AsRef, size: u16) -> Option { + pub fn icon(&self, path: impl AsRef, size: u16) -> Result { let path = path.as_ref(); let get_icon = |path| get_file_icon(path, size).map(self.convert); match path.extension() { Some(extension) => match self.cache.borrow_mut().entry((size, extension.to_owned())) { - Vacant(vacant_entry) => Some(vacant_entry.insert(get_icon(path)?).clone()), - Occupied(occupied_entry) => Some(occupied_entry.get().clone()), + Vacant(vacant_entry) => Ok(vacant_entry.insert(get_icon(path)?).clone()), + Occupied(occupied_entry) => Ok(occupied_entry.get().clone()), }, // No extension then no caching. None => get_icon(path),