You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

164 lines
3.9 KiB

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<String>),
}
impl Hash for LeanifyFlag {
fn hash<H: Hasher>(&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<P: AsRef<str>,T: Iterator<Item=S> + ?Sized, S: AsRef<str>>(path: P, iter: &mut T) -> Result<Option<Self>, 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<String>
{
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<Cow<'static, str>>;
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<LeanifyFlag>,
}
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<Item = Cow<'static, str>> + 'a
{
self.flags.iter().map(|x| x.clone().into_iter()).flatten()
}
}
pub type IntoIter = std::iter::FilterMap<std::collections::hash_set::IntoIter<LeanifyFlag>, fn (LeanifyFlag) -> Option<String>>; //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())
}
}