From 97e69d1dcc10d85617ceef7c68ee27dd83ea50eb Mon Sep 17 00:00:00 2001 From: Yuya Nishihara Date: Sun, 10 Mar 2024 14:17:11 +0900 Subject: [PATCH] index: add filter RevWalk adapter FilterRevset will be built on top. --- lib/src/default_index/rev_walk.rs | 48 +++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/lib/src/default_index/rev_walk.rs b/lib/src/default_index/rev_walk.rs index 35181190c..75637f8e6 100644 --- a/lib/src/default_index/rev_walk.rs +++ b/lib/src/default_index/rev_walk.rs @@ -39,6 +39,18 @@ pub(super) trait RevWalk { // The following methods are provided for convenience. They are not supposed // to be reimplemented. + /// Wraps in adapter that will filter items by the given `predicate`. + fn filter

(self, predicate: P) -> FilterRevWalk + where + Self: Sized, + P: FnMut(&I, &Self::Item) -> bool, + { + FilterRevWalk { + walk: self, + predicate, + } + } + /// Wraps in adapter that can peek one more item without consuming. fn peekable(self) -> PeekableRevWalk where @@ -82,6 +94,31 @@ impl RevWalk for EagerRevWalk { } } +#[derive(Clone, Debug)] +#[must_use] +pub(super) struct FilterRevWalk { + walk: W, + predicate: P, +} + +impl RevWalk for FilterRevWalk +where + I: ?Sized, + W: RevWalk, + P: FnMut(&I, &W::Item) -> bool, +{ + type Item = W::Item; + + fn next(&mut self, index: &I) -> Option { + while let Some(item) = self.walk.next(index) { + if (self.predicate)(index, &item) { + return Some(item); + } + } + None + } +} + #[derive(Clone, Debug)] #[must_use] pub(super) struct PeekableRevWalk> { @@ -778,6 +815,17 @@ mod tests { assert_eq!(peekable.next(&()), None); } + #[test] + fn test_filter_rev_walk() { + let source = EagerRevWalk::new(vec![0, 1, 2, 3, 4].into_iter()); + let mut filtered = source.filter(|_, &v| v & 1 == 0); + assert_eq!(filtered.next(&()), Some(0)); + assert_eq!(filtered.next(&()), Some(2)); + assert_eq!(filtered.next(&()), Some(4)); + assert_eq!(filtered.next(&()), None); + assert_eq!(filtered.next(&()), None); + } + #[test] fn test_walk_ancestors() { let mut new_change_id = change_id_generator();