file_matcher/
lib.rs

1#[cfg(feature = "fs_extra")]
2extern crate fs_extra;
3#[cfg(feature = "regex")]
4extern crate regex;
5#[cfg(feature = "wildmatch")]
6extern crate wildmatch;
7
8mod actions;
9mod alias;
10mod entries;
11mod error;
12mod finders;
13mod utils;
14
15use std::fmt::Debug;
16use std::path::PathBuf;
17
18#[cfg(feature = "serde")]
19use serde::{Serialize, Deserialize};
20
21pub use actions::*;
22pub use entries::*;
23
24pub use alias::EntityAlias;
25pub use error::{FileMatcherError, Result};
26
27/// Defines a file with various name types.
28/// It is required that there exists exactly one file with a given name description.
29/// ```
30/// use file_matcher::FileNamed;
31///
32/// # use file_matcher::Result;
33/// # fn main() -> Result<()> {
34///     // Find an exactly one file matching cat* within tests/assets folder
35///     FileNamed::wildmatch("cat*")
36///         .within("tests/assets")
37///         .find()?;
38///
39///     // Check there exists a file matching cat* within tests/assets folder
40///     FileNamed::wildmatch("cat*")
41///         .within("tests/assets")
42///         .exists()?;
43/// #    Ok(())
44/// # }
45/// ```
46#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
47#[derive(Debug, Clone)]
48pub struct FileNamed(EntryNamed);
49
50/// Defines a folder with various name types.
51/// It is required that there exists exactly one folder with a given name description.
52/// ```
53/// use file_matcher::FolderNamed;
54///
55/// # use file_matcher::Result;
56/// # fn main() -> Result<()> {
57///     // Find an exactly one folder matching cat* within tests/assets folder
58///     FolderNamed::wildmatch("cat*")
59///         .within("tests/assets")
60///         .find()?;
61///
62///     // Check there exists a folder matching cat* within tests/assets folder
63///     FolderNamed::wildmatch("cat*")
64///         .within("tests/assets")
65///         .exists()?;
66/// #    Ok(())
67/// # }
68/// ```
69#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
70#[derive(Debug, Clone)]
71pub struct FolderNamed(EntryNamed);
72
73/// Defines a file or a folder with various name types.
74/// It is required that there exists exactly one file or folder with a given name description.
75#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
76#[derive(Debug, Clone)]
77pub struct FileOrFolderNamed(EntryNamed);
78
79#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
80#[derive(Debug, Clone)]
81pub struct FilesNamed(EntryNamed);
82
83impl OneEntryNamed for FileNamed {
84    fn within_path_buf(&self, directory: PathBuf) -> OneEntry {
85        OneEntry::new(self.boxed(), directory)
86    }
87
88    fn entry_name(&self) -> &EntryName {
89        self.0.entry_name()
90    }
91
92    fn entry_type(&self) -> &EntryType {
93        self.0.entry_type()
94    }
95
96    fn name_alias(&self) -> Option<&str> {
97        None
98    }
99
100    fn boxed(&self) -> Box<dyn OneEntryNamed> {
101        Box::new(self.clone())
102    }
103}
104
105impl FileNamed {
106    pub fn exact(name: impl Into<String>) -> Self {
107        Self(EntryNamed::file(EntryName::Exact(name.into())))
108    }
109
110    pub fn any(names: Vec<impl Into<String>>) -> Self {
111        Self(EntryNamed::file(EntryName::Any(
112            names.into_iter().map(|name| name.into()).collect(),
113        )))
114    }
115
116    pub fn any_named(names: Vec<FileNamed>) -> Self {
117        Self(EntryNamed::file(EntryName::AnyNamed(
118            names
119                .into_iter()
120                .map(|name| name.entry_name().clone())
121                .collect(),
122        )))
123    }
124
125    #[cfg(feature = "regex")]
126    pub fn regex(pattern: impl Into<String>) -> Self {
127        Self(EntryNamed::file(EntryName::Regex(pattern.into())))
128    }
129
130    #[cfg(feature = "wildmatch")]
131    pub fn wildmatch(pattern: impl Into<String>) -> Self {
132        Self(EntryNamed::file(EntryName::Wildmatch(pattern.into())))
133    }
134
135    pub fn within(&self, directory: impl Into<PathBuf>) -> OneEntry {
136        self.within_path_buf(directory.into())
137    }
138
139    pub fn alias(&self, name: impl Into<String>) -> EntityAlias {
140        EntityAlias::new(Box::new(self.clone()), name)
141    }
142}
143
144impl OneEntryNamed for FolderNamed {
145    fn within_path_buf(&self, directory: PathBuf) -> OneEntry {
146        OneEntry::new(self.boxed(), directory)
147    }
148
149    fn entry_name(&self) -> &EntryName {
150        self.0.entry_name()
151    }
152
153    fn entry_type(&self) -> &EntryType {
154        self.0.entry_type()
155    }
156
157    fn name_alias(&self) -> Option<&str> {
158        None
159    }
160
161    fn boxed(&self) -> Box<dyn OneEntryNamed> {
162        Box::new(self.clone())
163    }
164}
165
166impl FolderNamed {
167    pub fn exact(name: impl Into<String>) -> Self {
168        Self(EntryNamed::folder(EntryName::Exact(name.into())))
169    }
170
171    pub fn any(names: Vec<impl Into<String>>) -> Self {
172        Self(EntryNamed::folder(EntryName::Any(
173            names.into_iter().map(|name| name.into()).collect(),
174        )))
175    }
176
177    pub fn any_named(names: Vec<FolderNamed>) -> Self {
178        Self(EntryNamed::folder(EntryName::AnyNamed(
179            names
180                .into_iter()
181                .map(|name| name.entry_name().clone())
182                .collect(),
183        )))
184    }
185
186    #[cfg(feature = "regex")]
187    pub fn regex(pattern: impl Into<String>) -> Self {
188        Self(EntryNamed::folder(EntryName::Regex(pattern.into())))
189    }
190
191    #[cfg(feature = "wildmatch")]
192    pub fn wildmatch(pattern: impl Into<String>) -> Self {
193        Self(EntryNamed::folder(EntryName::Wildmatch(pattern.into())))
194    }
195
196    pub fn within(&self, directory: impl Into<PathBuf>) -> OneEntry {
197        self.within_path_buf(directory.into())
198    }
199
200    pub fn alias(&self, name: impl Into<String>) -> EntityAlias {
201        EntityAlias::new(self.boxed(), name)
202    }
203}
204
205impl OneEntryNamed for FileOrFolderNamed {
206    fn within_path_buf(&self, directory: PathBuf) -> OneEntry {
207        OneEntry::new(self.boxed(), directory)
208    }
209
210    fn entry_name(&self) -> &EntryName {
211        self.0.entry_name()
212    }
213
214    fn entry_type(&self) -> &EntryType {
215        self.0.entry_type()
216    }
217
218    fn name_alias(&self) -> Option<&str> {
219        None
220    }
221
222    fn boxed(&self) -> Box<dyn OneEntryNamed> {
223        Box::new(self.clone())
224    }
225}
226
227impl FileOrFolderNamed {
228    pub fn exact(name: impl Into<String>) -> Self {
229        Self(EntryNamed::any(EntryName::Exact(name.into())))
230    }
231
232    pub fn any(names: Vec<impl Into<String>>) -> Self {
233        Self(EntryNamed::any(EntryName::Any(
234            names.into_iter().map(|name| name.into()).collect(),
235        )))
236    }
237
238    pub fn any_named(names: Vec<FileOrFolderNamed>) -> Self {
239        Self(EntryNamed::any(EntryName::AnyNamed(
240            names
241                .into_iter()
242                .map(|name| name.entry_name().clone())
243                .collect(),
244        )))
245    }
246
247    #[cfg(feature = "regex")]
248    pub fn regex(pattern: impl Into<String>) -> Self {
249        Self(EntryNamed::any(EntryName::Regex(pattern.into())))
250    }
251
252    #[cfg(feature = "wildmatch")]
253    pub fn wildmatch(pattern: impl Into<String>) -> Self {
254        Self(EntryNamed::any(EntryName::Wildmatch(pattern.into())))
255    }
256
257    pub fn within(&self, directory: impl Into<PathBuf>) -> OneEntry {
258        self.within_path_buf(directory.into())
259    }
260
261    pub fn alias(&self, name: impl Into<String>) -> EntityAlias {
262        EntityAlias::new(Box::new(self.clone()), name)
263    }
264}
265
266impl ManyEntriesNamed for FilesNamed {
267    fn within_path_buf(&self, directory: PathBuf) -> ManyEntries {
268        ManyEntries::new(self.boxed(), directory)
269    }
270
271    fn entry_name(&self) -> &EntryName {
272        self.0.entry_name()
273    }
274
275    fn entry_type(&self) -> &EntryType {
276        self.0.entry_type()
277    }
278
279    fn name_alias(&self) -> Option<&str> {
280        None
281    }
282
283    fn boxed(&self) -> Box<dyn ManyEntriesNamed> {
284        Box::new(self.clone())
285    }
286}
287
288impl FilesNamed {
289    pub fn exact(name: impl Into<String>) -> Self {
290        Self(EntryNamed::file(EntryName::Exact(name.into())))
291    }
292
293    pub fn any(names: Vec<impl Into<String>>) -> Self {
294        Self(EntryNamed::file(EntryName::Any(
295            names.into_iter().map(|name| name.into()).collect(),
296        )))
297    }
298
299    #[cfg(feature = "regex")]
300    pub fn regex(pattern: impl Into<String>) -> Self {
301        Self(EntryNamed::file(EntryName::Regex(pattern.into())))
302    }
303
304    #[cfg(feature = "wildmatch")]
305    pub fn wildmatch(pattern: impl Into<String>) -> Self {
306        Self(EntryNamed::file(EntryName::Wildmatch(pattern.into())))
307    }
308
309    pub fn within(&self, directory: impl Into<PathBuf>) -> ManyEntries {
310        ManyEntries::new(self.boxed(), directory)
311    }
312}