1use std::{cmp::Ordering, path::PathBuf};
2use strum::{AsRefStr, EnumIter, EnumString, EnumVariantNames};
3pub mod cli;
4
5pub trait IterExt: Iterator + Sized {
6 fn max_by_maybe_key<F, K>(self, key_fn: F) -> Option<Self::Item>
8 where
9 F: Fn(&Self::Item) -> Option<K>,
10 K: Ord,
11 {
12 let winner = self
13 .filter_map(|path| {
14 let key = key_fn(&path)?;
15 Some((path, key))
16 })
17 .reduce(|winner, challenger| match winner.1.cmp(&challenger.1) {
18 Ordering::Greater => winner,
19 Ordering::Equal | Ordering::Less => challenger,
20 })?;
21 Some(winner.0)
22 }
23}
24
25impl<T> IterExt for T where T: Iterator + Sized {}
26
27#[derive(Debug, EnumString, EnumVariantNames, AsRefStr, EnumIter)]
28#[strum(serialize_all = "kebab_case")]
29pub enum Method {
30 Accessed,
31 Created,
32 Modified,
33}
34
35pub trait MostRecently: Iterator<Item = PathBuf> + Sized {
36 fn most_recently(self, method: Method) -> Option<Self::Item> {
37 match method {
38 Method::Accessed => {
39 self.max_by_maybe_key(|path_buf| path_buf.metadata().ok()?.accessed().ok())
40 }
41 Method::Created => {
42 self.max_by_maybe_key(|path_buf| path_buf.metadata().ok()?.created().ok())
43 }
44 Method::Modified => {
45 self.max_by_maybe_key(|path_buf| path_buf.metadata().ok()?.modified().ok())
46 }
47 }
48 }
49}
50
51impl<T> MostRecently for T where T: Iterator<Item = PathBuf> {}