rust_search/
filter.rs

1use super::SearchBuilder;
2use ignore::DirEntry;
3use std::{cmp::Ordering, time::SystemTime};
4
5/// custom filter fn to expose the dir entry directly
6pub type FilterFn = fn(&DirEntry) -> bool;
7
8#[derive(Clone, Copy)]
9pub enum FilterType {
10    Created(Ordering, SystemTime),
11    Modified(Ordering, SystemTime),
12    FileSize(Ordering, u64),
13    Custom(FilterFn),
14}
15
16impl FilterType {
17    pub fn apply(&self, dir: &DirEntry) -> bool {
18        if let Ok(m) = dir.metadata() {
19            match self {
20                FilterType::Created(cmp, time) => {
21                    if let Ok(created) = m.created() {
22                        return created.cmp(time) == *cmp;
23                    }
24                }
25                FilterType::Modified(cmp, time) => {
26                    if let Ok(modified) = m.modified() {
27                        return modified.cmp(time) == *cmp;
28                    }
29                }
30                FilterType::FileSize(cmp, size_in_bytes) => {
31                    return m.len().cmp(size_in_bytes) == *cmp;
32                }
33                FilterType::Custom(f) => return f(dir),
34            }
35        }
36        false
37    }
38}
39
40/// enum to easily convert between byte_sizes
41#[derive(Debug, Clone)]
42pub enum FileSize {
43    /// size in bytes
44    Byte(u64),
45    /// size in kilobytes
46    Kilobyte(f64),
47    /// size in megabytes
48    Megabyte(f64),
49    /// size in gigabytes
50    Gigabyte(f64),
51    /// size in terabytes
52    Terabyte(f64),
53}
54
55// helper function for FileSize conversion
56fn convert(b: f64, pow: u32) -> u64 {
57    (b * 1024_u64.pow(pow) as f64) as u64
58}
59
60#[allow(clippy::from_over_into)]
61impl Into<u64> for FileSize {
62    fn into(self) -> u64 {
63        use self::FileSize::*;
64        match self {
65            Byte(b) => b,
66            Kilobyte(b) => convert(b, 1),
67            Megabyte(b) => convert(b, 2),
68            Gigabyte(b) => convert(b, 3),
69            Terabyte(b) => convert(b, 4),
70        }
71    }
72}
73
74/// import this trait to filter files
75pub trait FilterExt {
76    /// files created before `t`: [SystemTime]
77    fn created_before(self, t: SystemTime) -> Self;
78    /// files created at `t`: [SystemTime]
79    fn created_at(self, t: SystemTime) -> Self;
80    /// files created after `t`: [SystemTime]
81    fn created_after(self, t: SystemTime) -> Self;
82    /// files created before `t`: [SystemTime]
83    fn modified_before(self, t: SystemTime) -> Self;
84    /// files modified at `t`: [SystemTime]
85    fn modified_at(self, t: SystemTime) -> Self;
86    /// files modified after `t`: [SystemTime]
87    fn modified_after(self, t: SystemTime) -> Self;
88    /// files smaller than `size_in_bytes`: [usize]
89    fn file_size_smaller(self, size: FileSize) -> Self;
90    /// files equal to `size_in_bytes`: [usize]
91    fn file_size_equal(self, size: FileSize) -> Self;
92    /// files greater than `size_in_bytes`: [usize]
93    fn file_size_greater(self, size: FileSize) -> Self;
94    /// custom filter that exposes the [DirEntry] directly
95    /// ```rust
96    /// builder.custom_filter(|dir| dir.metadata().unwrap().is_file())
97    /// ```
98    fn custom_filter(self, f: FilterFn) -> Self;
99}
100
101use FilterType::*;
102use Ordering::*;
103impl FilterExt for SearchBuilder {
104    fn created_before(self, t: SystemTime) -> Self {
105        self.filter(Created(Less, t))
106    }
107
108    fn created_at(self, t: SystemTime) -> Self {
109        self.filter(Created(Equal, t))
110    }
111
112    fn created_after(self, t: SystemTime) -> Self {
113        self.filter(Created(Greater, t))
114    }
115
116    fn modified_before(self, t: SystemTime) -> Self {
117        self.filter(Modified(Less, t))
118    }
119
120    fn modified_at(self, t: SystemTime) -> Self {
121        self.filter(Modified(Equal, t))
122    }
123
124    fn modified_after(self, t: SystemTime) -> Self {
125        self.filter(Modified(Greater, t))
126    }
127
128    fn file_size_smaller(self, size: FileSize) -> Self {
129        self.filter(FileSize(Less, size.into()))
130    }
131
132    fn file_size_equal(self, size: FileSize) -> Self {
133        self.filter(FileSize(Equal, size.into()))
134    }
135
136    fn file_size_greater(self, size: FileSize) -> Self {
137        self.filter(FileSize(Greater, size.into()))
138    }
139    fn custom_filter(self, f: FilterFn) -> Self {
140        self.filter(Custom(f))
141    }
142}