use super::*; use std::{ collections::HashSet, num::NonZeroUsize, hash::{Hash, Hasher}, borrow::Cow, }; /// Flags for `leanify` #[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd)] pub enum LeanifyFlag { /// Corresponds to `-i` Iteration(NonZeroUsize), /// Corresponds to `-d` Depth(NonZeroUsize), /// Corresponds to `-f` Fastmode, /// Corresponds to `-q` Quiet, /// Corresponds to `-v` Verbose, /// Corresponds to `--keep-exif` KeepExif, /// Any other the user specified Custom(Vec), } impl Hash for LeanifyFlag { fn hash(&self, state: &mut H) { // Don't let us pass multiple of the same discriminant when their inner values are different if let Self::Custom(custom) = self { // Except custom custom.hash(state) } std::mem::discriminant(self).hash(state); } } impl LeanifyFlag { pub fn try_parse,T: Iterator + ?Sized, S: AsRef>(path: P, iter: &mut T) -> Result, arg::Error> { Ok(match path.as_ref() { "-i" | "--iteration" => { if let Some(iter) = iter.next() { Some(Self::Iteration(iter.as_ref().parse()?)) } else { None } }, "-d" | "--max_depth" => { if let Some(iter) = iter.next() { Some(Self::Depth(iter.as_ref().parse()?)) } else { None } }, "-f" | "--fastmode" => { Some(Self::Fastmode) }, "-q" | "--quiet" => { Some(Self::Quiet) }, "-v" | "--verbose" => { Some(Self::Verbose) }, "--keep-exif" => { Some(Self::KeepExif) }, _ => None, }) } fn try_into_string(self) -> Option { Some(match self { Self::Iteration(iter) => format!("--iteration {}", iter), Self::Depth(depth) => format!("--max_depth {}", depth), Self::Fastmode => format!("-f"), Self::Quiet => format!("-q"), Self::Verbose => format!("-v"), Self::KeepExif => format!("--keep-exif"), Self::Custom(string) => string.into_iter().join(" "), }) } } impl IntoIterator for LeanifyFlag { type Item= Cow<'static, str>; type IntoIter = maybe_single::IntoIter>; fn into_iter(self) -> Self::IntoIter { use maybe_single::MaybeSingle; match self { Self::Iteration(iter) => MaybeSingle::from(vec![Cow::Borrowed("--iteration"), Cow::Owned(iter.to_string())]), Self::Depth(depth) => MaybeSingle::from(vec![Cow::Borrowed("--max_depth"), Cow::Owned(depth.to_string())]), Self::Fastmode => MaybeSingle::single(Cow::Borrowed("-f")), Self::Quiet => MaybeSingle::single(Cow::Borrowed("-q")), Self::Verbose => MaybeSingle::single(Cow::Borrowed("-v")), Self::KeepExif => MaybeSingle::single(Cow::Borrowed("--keep-exif")), Self::Custom(string) => string.into_iter().map(|x| Cow::Owned(x)).collect(), }.into_iter() } } /// Extra flags to pass to `leanify` #[derive(Debug, Clone, PartialEq, Eq)] pub struct LeanifyFlags { flags: HashSet, } impl Default for LeanifyFlags { #[inline] fn default() -> Self { Self{flags:HashSet::new()} } } impl LeanifyFlags { /// Create a new empty flag list #[inline] pub fn new() -> Self { Self::default() } /// Add one pub fn add(&mut self, flag: LeanifyFlag) { self.flags.insert(flag); } /// Create the `leanify` arg string pub fn into_arg_string(self) -> String { self.flags.into_iter().filter_map(|x| x.try_into_string()).join(" ") } pub fn iter_cloned<'a>(&'a self) -> impl Iterator> + 'a { self.flags.iter().map(|x| x.clone().into_iter()).flatten() } } pub type IntoIter = std::iter::FilterMap, fn (LeanifyFlag) -> Option>; //fuck this is annoying impl IntoIterator for LeanifyFlags { type Item= String; type IntoIter = IntoIter; fn into_iter(self) -> Self::IntoIter { self.flags.into_iter().filter_map(|x| x.try_into_string()) } }