ok/jj
1
0
Fork 0
forked from mirrors/jj

revset: extract generic combination iterators

I'm going to add pre-filtering to the 'roots..heads' evaluation path, and
difference_by() will be used there to calculate 'heads ~ roots'.

Union and intersection iterators are slightly changed so that all iterators
prioritize iter1's item.
This commit is contained in:
Yuya Nishihara 2024-02-20 12:13:47 +09:00
parent c32b68eb83
commit 22933563e8

View file

@ -338,10 +338,11 @@ where
&'a self,
index: CompositeIndex<'index>,
) -> Box<dyn Iterator<Item = IndexEntry<'index>> + 'a> {
Box::new(UnionRevsetIterator {
iter1: self.set1.iter(index).peekable(),
iter2: self.set2.iter(index).peekable(),
})
Box::new(union_by(
self.set1.iter(index),
self.set2.iter(index),
|entry1, entry2| entry1.position().cmp(&entry2.position()),
))
}
fn into_predicate<'a>(self: Box<Self>) -> Box<dyn ToPredicateFn + 'a>
@ -367,27 +368,32 @@ where
}
}
struct UnionRevsetIterator<I1: Iterator, I2: Iterator> {
/// Iterator that merges two sorted iterators.
///
/// The input items should be sorted in descending order by the `cmp` function.
struct UnionByIterator<I1: Iterator, I2: Iterator, C> {
iter1: Peekable<I1>,
iter2: Peekable<I2>,
cmp: C,
}
impl<'index, I1, I2> Iterator for UnionRevsetIterator<I1, I2>
impl<I1, I2, C> Iterator for UnionByIterator<I1, I2, C>
where
I1: Iterator<Item = IndexEntry<'index>>,
I2: Iterator<Item = IndexEntry<'index>>,
I1: Iterator,
I2: Iterator<Item = I1::Item>,
C: FnMut(&I1::Item, &I2::Item) -> Ordering,
{
type Item = IndexEntry<'index>;
type Item = I1::Item;
fn next(&mut self) -> Option<Self::Item> {
match (self.iter1.peek(), self.iter2.peek()) {
(None, _) => self.iter2.next(),
(_, None) => self.iter1.next(),
(Some(entry1), Some(entry2)) => match entry1.position().cmp(&entry2.position()) {
(Some(item1), Some(item2)) => match (self.cmp)(item1, item2) {
Ordering::Less => self.iter2.next(),
Ordering::Equal => {
self.iter1.next();
self.iter2.next()
self.iter2.next();
self.iter1.next()
}
Ordering::Greater => self.iter1.next(),
},
@ -395,6 +401,23 @@ where
}
}
fn union_by<I1, I2, C>(
iter1: I1,
iter2: I2,
cmp: C,
) -> UnionByIterator<I1::IntoIter, I2::IntoIter, C>
where
I1: IntoIterator,
I2: IntoIterator<Item = I1::Item>,
C: FnMut(&I1::Item, &I2::Item) -> Ordering,
{
UnionByIterator {
iter1: iter1.into_iter().peekable(),
iter2: iter2.into_iter().peekable(),
cmp,
}
}
#[derive(Debug)]
struct IntersectionRevset<S1, S2> {
set1: S1,
@ -410,10 +433,11 @@ where
&'a self,
index: CompositeIndex<'index>,
) -> Box<dyn Iterator<Item = IndexEntry<'index>> + 'a> {
Box::new(IntersectionRevsetIterator {
iter1: self.set1.iter(index).peekable(),
iter2: self.set2.iter(index).peekable(),
})
Box::new(intersection_by(
self.set1.iter(index),
self.set2.iter(index),
|entry1, entry2| entry1.position().cmp(&entry2.position()),
))
}
fn into_predicate<'a>(self: Box<Self>) -> Box<dyn ToPredicateFn + 'a>
@ -439,17 +463,22 @@ where
}
}
struct IntersectionRevsetIterator<I1: Iterator, I2: Iterator> {
/// Iterator that intersects two sorted iterators.
///
/// The input items should be sorted in descending order by the `cmp` function.
struct IntersectionByIterator<I1: Iterator, I2: Iterator, C> {
iter1: Peekable<I1>,
iter2: Peekable<I2>,
cmp: C,
}
impl<'index, I1, I2> Iterator for IntersectionRevsetIterator<I1, I2>
impl<I1, I2, C> Iterator for IntersectionByIterator<I1, I2, C>
where
I1: Iterator<Item = IndexEntry<'index>>,
I2: Iterator<Item = IndexEntry<'index>>,
I1: Iterator,
I2: Iterator,
C: FnMut(&I1::Item, &I2::Item) -> Ordering,
{
type Item = IndexEntry<'index>;
type Item = I1::Item;
fn next(&mut self) -> Option<Self::Item> {
loop {
@ -460,13 +489,13 @@ where
(_, None) => {
return None;
}
(Some(entry1), Some(entry2)) => match entry1.position().cmp(&entry2.position()) {
(Some(item1), Some(item2)) => match (self.cmp)(item1, item2) {
Ordering::Less => {
self.iter2.next();
}
Ordering::Equal => {
self.iter1.next();
return self.iter2.next();
self.iter2.next();
return self.iter1.next();
}
Ordering::Greater => {
self.iter1.next();
@ -477,6 +506,23 @@ where
}
}
fn intersection_by<I1, I2, C>(
iter1: I1,
iter2: I2,
cmp: C,
) -> IntersectionByIterator<I1::IntoIter, I2::IntoIter, C>
where
I1: IntoIterator,
I2: IntoIterator,
C: FnMut(&I1::Item, &I2::Item) -> Ordering,
{
IntersectionByIterator {
iter1: iter1.into_iter().peekable(),
iter2: iter2.into_iter().peekable(),
cmp,
}
}
#[derive(Debug)]
struct DifferenceRevset<S1, S2> {
// The minuend (what to subtract from)
@ -494,10 +540,11 @@ where
&'a self,
index: CompositeIndex<'index>,
) -> Box<dyn Iterator<Item = IndexEntry<'index>> + 'a> {
Box::new(DifferenceRevsetIterator {
iter1: self.set1.iter(index).peekable(),
iter2: self.set2.iter(index).peekable(),
})
Box::new(difference_by(
self.set1.iter(index),
self.set2.iter(index),
|entry1, entry2| entry1.position().cmp(&entry2.position()),
))
}
fn into_predicate<'a>(self: Box<Self>) -> Box<dyn ToPredicateFn + 'a>
@ -523,17 +570,22 @@ where
}
}
struct DifferenceRevsetIterator<I1: Iterator, I2: Iterator> {
/// Iterator that subtracts `iter2` items from `iter1`.
///
/// The input items should be sorted in descending order by the `cmp` function.
struct DifferenceByIterator<I1: Iterator, I2: Iterator, C> {
iter1: Peekable<I1>,
iter2: Peekable<I2>,
cmp: C,
}
impl<'index, I1, I2> Iterator for DifferenceRevsetIterator<I1, I2>
impl<I1, I2, C> Iterator for DifferenceByIterator<I1, I2, C>
where
I1: Iterator<Item = IndexEntry<'index>>,
I2: Iterator<Item = IndexEntry<'index>>,
I1: Iterator,
I2: Iterator,
C: FnMut(&I1::Item, &I2::Item) -> Ordering,
{
type Item = IndexEntry<'index>;
type Item = I1::Item;
fn next(&mut self) -> Option<Self::Item> {
loop {
@ -544,7 +596,7 @@ where
(_, None) => {
return self.iter1.next();
}
(Some(entry1), Some(entry2)) => match entry1.position().cmp(&entry2.position()) {
(Some(item1), Some(item2)) => match (self.cmp)(item1, item2) {
Ordering::Less => {
self.iter2.next();
}
@ -561,6 +613,23 @@ where
}
}
fn difference_by<I1, I2, C>(
iter1: I1,
iter2: I2,
cmp: C,
) -> DifferenceByIterator<I1::IntoIter, I2::IntoIter, C>
where
I1: IntoIterator,
I2: IntoIterator,
C: FnMut(&I1::Item, &I2::Item) -> Ordering,
{
DifferenceByIterator {
iter1: iter1.into_iter().peekable(),
iter2: iter2.into_iter().peekable(),
cmp,
}
}
pub fn evaluate<I: AsCompositeIndex>(
expression: &ResolvedExpression,
store: &Arc<Store>,