use std::{env, ffi::OsString, fs}; const ICON_FILE_EXTENSION: &'static str = ".svg"; pub const ICON_FILE_EXTENSION_LEN: usize = ICON_FILE_EXTENSION.len(); pub struct Icons { icons_dir_path: String, icon_filenames: Vec, } impl Icons { /// Build the Icons (handler) struct /// /// Returns a result with the Icons struct or an error message pub fn build() -> Result { let icons_dir_arg = env::args() .nth(1) .unwrap_or(String::from("vendor/lucide/icons")); let icon_dir = match fs::read_dir(&icons_dir_arg) { Ok(dir) => dir, Err(_) => return Err("Failed to read icon directory"), }; let icon_filenames: Vec<_> = icon_dir .map(|entry| entry.unwrap().file_name()) .filter(|entry| entry.to_str().unwrap_or("").ends_with(".svg")) .collect(); Ok(Icons { icons_dir_path: icons_dir_arg, icon_filenames, }) } /// Check if the icon exists /// /// Cheap; does not actually call the fs - instead checks against the cached filenames in the Vec internal to this struct. /// Therefore, it is not guaranteed to be up-to-date with the actual filesystem /// /// icon: the icon name to check (no .svg extension) pub fn has_iconname(&self, icon: &str) -> bool { self.icon_filenames .iter() .find(|&i| match i.to_str() { Some(i) => &i[..i.len() - ICON_FILE_EXTENSION_LEN] == icon, None => false, }) .is_some() } /// Get the number of icons /// /// Cheap; does not actually call the fs - instead returns the length of the cached filenames in the Vec internal to this struct. pub fn icons_len(&self) -> usize { self.icon_filenames.len() } /// Read an .svg icon from disk to a Vec /// /// You may want to check if the icon exists first with has_iconname(), although that method does not guarantee the icon is still present on the disk. /// /// icon: the icon name to read (no .svg extension) pub fn get_icon(&self, icon: &str) -> Option> { let icon_path = format!("{}/{}.svg", self.icons_dir_path, icon); fs::read(icon_path).ok() } /// Read an .svg icon from disk to a String, instead of a Vec /// /// You may want to check if the icon exists first with has_iconname(), although that method does not guarantee the icon is still present on the disk. /// /// icon: the icon name to read (no .svg extension) pub fn get_icon_string(&self, icon: &str) -> Option { let icon_path = format!("{}/{}.svg", self.icons_dir_path, icon); fs::read_to_string(icon_path).ok() } }