summaryrefslogtreecommitdiffstats
path: root/src/search.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/search.rs')
-rw-r--r--src/search.rs129
1 files changed, 129 insertions, 0 deletions
diff --git a/src/search.rs b/src/search.rs
new file mode 100644
index 0000000..e39d67b
--- /dev/null
+++ b/src/search.rs
@@ -0,0 +1,129 @@
+use figment::Provider;
+use std::vec::IntoIter;
+
+use crate::{Config, Project, Result};
+
+pub use entry::Entry;
+
+pub mod entry;
+
+pub struct Search {
+ iter: IntoIter<entry::Config>,
+ curr: Option<Entry>,
+}
+
+impl std::fmt::Debug for Search {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("Projects")
+ .field("paths_iter", &self.iter)
+ .finish_non_exhaustive()
+ }
+}
+
+impl Search {
+ pub fn new() -> Result<Self> {
+ Self::from_provider(Config::figment())
+ }
+
+ /// Extract `Config` from `provider` to construct new `Paths`
+ pub fn from_provider<T: Provider>(provider: T) -> Result<Self> {
+ Config::extract(&provider)
+ .map_err(Into::into)
+ .map(|config| config.paths.into())
+ }
+}
+
+// impl<T> From<T> for Search
+// where
+// T: IntoIterator<Item = entry::Config, IntoIter = IntoIter<entry::Config>>,
+// {
+// fn from(value: T) -> Self {
+// Self {
+// iter: value.into_iter(),
+// curr: None,
+// }
+// }
+// }
+
+impl From<Vec<entry::Config>> for Search {
+ fn from(value: Vec<entry::Config>) -> Self {
+ Self {
+ iter: value.into_iter(),
+ curr: None,
+ }
+ }
+}
+
+impl From<Config> for Search {
+ fn from(value: Config) -> Self {
+ value.paths.into()
+ }
+}
+
+impl Iterator for Search {
+ type Item = Box<dyn Project>;
+
+ #[tracing::instrument]
+ fn next(&mut self) -> Option<Self::Item> {
+ match self.curr.as_mut().and_then(|c| c.next()) {
+ Some(proj) => Some(proj),
+ None => {
+ self.curr = Some(self.iter.next()?.into());
+ self.next()
+ }
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use pretty_assertions::assert_eq;
+ use std::{fs, path::PathBuf};
+
+ #[test]
+ fn test_iteration() {
+ let temp_dir = tempfile::Builder::new()
+ .tempdir()
+ .unwrap()
+ .path()
+ .to_owned();
+
+ let project_dir = temp_dir.join("project_dir");
+ let project1 = temp_dir.join("project_dir/project1");
+ let project2 = temp_dir.join("project_dir/project2");
+ let project3 = temp_dir.join("project3");
+ let project4 = temp_dir.join("subdir/project4");
+
+ let paths = Search::from(Vec::from([
+ entry::Config {
+ path_buf: project_dir.to_owned(),
+ max_depth: Some(1),
+ ..Default::default()
+ },
+ entry::Config {
+ path_buf: project3.to_owned(),
+ max_depth: Some(0),
+ ..Default::default()
+ },
+ entry::Config {
+ path_buf: project4.to_owned(),
+ max_depth: Some(0),
+ ..Default::default()
+ },
+ ]));
+
+ let mut path_bufs = Vec::from([project_dir, project1, project2, project3, project4]);
+ path_bufs.iter().try_for_each(fs::create_dir_all).unwrap();
+ path_bufs.sort();
+
+ let mut results = paths.into_iter().collect::<Vec<Box<dyn Project>>>();
+ results.sort_unstable_by_key(|p| p.timestamp());
+ let results = results
+ .into_iter()
+ .map(|p| p.to_path_buf())
+ .collect::<Vec<PathBuf>>();
+
+ assert_eq!(path_bufs, results);
+ }
+}