Skip to content

Commit

Permalink
Implement a more advanced and efficient PathProvider for Glob
Browse files Browse the repository at this point in the history
Signed-off-by: MOZGIII <[email protected]>
  • Loading branch information
MOZGIII committed May 11, 2020
1 parent 785f6a2 commit 0228c05
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 4 deletions.
22 changes: 22 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions lib/file-source/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ flate2 = "1.0.6"
winapi = { version = "0.3", features = ["winioctl"] }
libc = "0.2"
tokio = { version = "0.2.13", features = ["time"] }
rental = "0.5"

[dev-dependencies]
quickcheck = "0.6"
Expand Down
2 changes: 2 additions & 0 deletions lib/file-source/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
extern crate scan_fmt;
#[macro_use]
extern crate tracing;
#[macro_use]
extern crate rental;

mod file_server;
mod file_watcher;
Expand Down
58 changes: 55 additions & 3 deletions lib/file-source/src/paths_provider/glob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,60 @@ impl<'a> Iterator for Iter<'a> {
}
}

impl PathsProvider for Glob {
fn paths(&self) -> Vec<PathBuf> {
self.iter().collect()
impl<'a> PathsProvider for &'a Glob {
type IntoIter = Iter<'a>;

fn paths(&self) -> Self::IntoIter {
self.iter()
}
}

/// Workaround for the absense of the GATs in Rust.
pub mod gat_workaround {
use std::sync::Arc;
use super::*;

impl Glob {
/// Create a new [`Glob`] wrapped in [`Arc`].
///
/// `Arc<Glob>` implements [`PathsProvider`] with low overhead.
/// This complexity is required while Rust doesn't have GATs.
///
/// Returns `None` if patterns aren't valid.
pub fn new_arc(
include_patterns: &[PathBuf],
exclude_patterns: &[PathBuf],
glob_match_options: MatchOptions,
) -> Option<Arc<Self>> {
Some(Arc::new(Self::new(include_patterns, exclude_patterns, glob_match_options)?))
}
}

rental! {
#[allow(missing_docs)]
pub mod rent_iter {
use super::*;
#[rental]
pub struct RentIter {
head: Arc<Glob>,
tail: Iter<'head>,
}
}
}

impl Iterator for rent_iter::RentIter {
type Item = PathBuf;

fn next(&mut self) -> Option<Self::Item> {
self.rent_mut(|val| Iter::next(val))
}
}

impl PathsProvider for Arc<Glob> {
type IntoIter = rent_iter::RentIter;

fn paths(&self) -> Self::IntoIter {
rent_iter::RentIter::new(self.clone(), |glob| glob.iter())
}
}
}
2 changes: 1 addition & 1 deletion src/sources/file/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ pub fn file_source(
.map(|secs| SystemTime::now() - Duration::from_secs(secs));
let glob_minimum_cooldown = Duration::from_millis(config.glob_minimum_cooldown);

let paths_provider = Glob::new(&config.include, &config.exclude, MatchOptions::default())
let paths_provider = Glob::new_arc(&config.include, &config.exclude, MatchOptions::default())
.expect("invalid glob patterns");

let file_server = FileServer {
Expand Down

0 comments on commit 0228c05

Please sign in to comment.