most_recently/
lib.rs

1use std::{cmp::Ordering, path::PathBuf};
2use strum::{AsRefStr, EnumIter, EnumString, EnumVariantNames};
3pub mod cli;
4
5pub trait IterExt: Iterator + Sized {
6    /// Allows the user to provide a fallible key
7    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> {}