Skip to content

Commit

Permalink
[wip] Use RPITIT in walk and iterator APIs.
Browse files Browse the repository at this point in the history
  • Loading branch information
olson-sean-k committed Dec 29, 2023
1 parent a7a02f6 commit 4842af7
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 131 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
matrix:
os: [macOS-latest, ubuntu-latest, windows-latest]
toolchain:
- 1.66.1 # Minimum.
- 1.75.0 # Minimum.
- stable
- beta
- nightly
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description = "Opinionated and portable globs that can be matched against paths
repository = "https://github.com/olson-sean-k/wax"
readme = "README.md"
edition = "2021"
rust-version = "1.66.1"
rust-version = "1.75.0"
license = "MIT"
keywords = [
"glob",
Expand Down
86 changes: 25 additions & 61 deletions src/walk/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,14 @@ impl<T, R> Feed for (T, R) {
type Residue = R;
}

pub trait TreeFeed: Feed<Residue = TreeResidue<Self::Residual>> {
type Residual;
}

impl<T, R> TreeFeed for (T, TreeResidue<R>) {
type Residual = R;
}

/// A filter [`Feed`] wherein the filtrate and residue have or can produce a substituent.
///
/// A substituent is data that is common to both the filtrate and residue (that is, the filtrate
Expand Down Expand Up @@ -505,19 +513,30 @@ impl<T> TreeResidue<T> {
pub trait HierarchicalIterator:
CancelWalk + Iterator<Item = <Self::Feed as Feed>::Filtrate> + SeparatingFilter
{
fn filter_tree_by_substituent<F>(self, f: F) -> FilterTreeBySubstituent<Self, F>
fn filter_tree_by_substituent<F>(self, mut f: F) -> impl HierarchicalIterator<Feed = Self::Feed>
where
Self: Sized,
Self::Feed: Isomeric,
Self::Feed: TreeFeed + Isomeric,
<Self::Feed as TreeFeed>::Residual: From<<Self::Feed as Feed>::Filtrate>,
F: FnMut(<Self::Feed as Isomeric>::Substituent<'_>) -> Option<TreeResidue<()>>,
{
FilterTreeBySubstituent { input: self, f }
self.filter_map_tree(move |cancellation, separation| {
let substituent = separation.substituent();
match f(substituent) {
None => separation,
Some(residue) => match residue {
TreeResidue::Node(_) => separation.filter_map_node(From::from),
TreeResidue::Tree(_) => separation.filter_map_tree(cancellation, From::from),
},
}
})
}

fn filter_map_tree<S, F>(self, f: F) -> FilterMapTree<Self, S, F>
fn filter_map_tree<S, F>(self, f: F) -> impl HierarchicalIterator<Feed = S>
where
Self: Sized,
S: Feed,
Self::Feed: TreeFeed,
S: TreeFeed,
F: FnMut(WalkCancellation<Self>, Separation<Self::Feed>) -> Separation<S>,
{
FilterMapTree {
Expand All @@ -536,62 +555,7 @@ where
}

#[derive(Clone, Debug)]
pub struct FilterTreeBySubstituent<I, F> {
input: I,
f: F,
}

impl<I, F> CancelWalk for FilterTreeBySubstituent<I, F>
where
I: CancelWalk,
{
fn cancel_walk_tree(&mut self) {
self.input.cancel_walk_tree()
}
}

impl<R, I, F> SeparatingFilter for FilterTreeBySubstituent<I, F>
where
R: From<<I::Feed as Feed>::Filtrate>,
I: HierarchicalIterator,
I::Feed: Feed<Residue = TreeResidue<R>> + Isomeric,
F: FnMut(<I::Feed as Isomeric>::Substituent<'_>) -> Option<TreeResidue<()>>,
{
type Feed = I::Feed;

fn feed(&mut self) -> Option<Separation<Self::Feed>> {
let separation = self.input.feed();
separation.map(|separation| {
let substituent = separation.substituent();
match (self.f)(substituent) {
None => separation,
Some(residue) => match residue {
TreeResidue::Node(_) => separation.filter_map_node(From::from),
TreeResidue::Tree(_) => {
separation.filter_map_tree(WalkCancellation(self), From::from)
},
},
}
})
}
}

impl<R, I, F> Iterator for FilterTreeBySubstituent<I, F>
where
R: From<<I::Feed as Feed>::Filtrate>,
I: HierarchicalIterator,
I::Feed: Feed<Residue = TreeResidue<R>> + Isomeric,
F: FnMut(<I::Feed as Isomeric>::Substituent<'_>) -> Option<TreeResidue<()>>,
{
type Item = <I::Feed as Feed>::Filtrate;

fn next(&mut self) -> Option<Self::Item> {
filtrate(self)
}
}

#[derive(Clone, Debug)]
pub struct FilterMapTree<I, S, F> {
struct FilterMapTree<I, S, F> {
input: I,
f: F,
_phantom: PhantomData<fn() -> S>,
Expand Down
9 changes: 6 additions & 3 deletions src/walk/glob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ impl<'t> Glob<'t> {
pub fn walk(
&self,
directory: impl Into<PathBuf>,
) -> impl 'static + FileIterator<Entry = GlobEntry> {
) -> impl 'static + FileIterator<Entry = GlobEntry, Residue = TreeEntry> {
self.walk_with_behavior(directory, WalkBehavior::default())
}

Expand Down Expand Up @@ -143,7 +143,7 @@ impl<'t> Glob<'t> {
&self,
directory: impl Into<PathBuf>,
behavior: impl Into<WalkBehavior>,
) -> impl 'static + FileIterator<Entry = GlobEntry> {
) -> impl 'static + FileIterator<Entry = GlobEntry, Residue = TreeEntry> {
self.walker(directory).walk_with_behavior(behavior)
}

Expand Down Expand Up @@ -231,7 +231,10 @@ impl Anchor {
self.root.split_at_depth(self.prefix)
}

pub fn walk_with_behavior(self, behavior: impl Into<WalkBehavior>) -> WalkTree {
pub fn walk_with_behavior(
self,
behavior: impl Into<WalkBehavior>,
) -> impl 'static + FileIterator<Entry = TreeEntry, Residue = TreeEntry> {
WalkTree::with_prefix_and_behavior(self.root, self.prefix, behavior)
}
}
Expand Down
Loading

0 comments on commit 4842af7

Please sign in to comment.