Skip to content

Commit 6bf03e0

Browse files
author
Andrew Jeffery
committed
Add ability to skip in tree searches
1 parent 8baacb2 commit 6bf03e0

File tree

3 files changed

+49
-19
lines changed

3 files changed

+49
-19
lines changed

automerge/src/op_tree.rs

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ impl OpTreeInternal {
9898
self.root_node
9999
.as_ref()
100100
.map(|root| match query.query_node_with_metadata(root, m) {
101-
QueryResult::Descend => root.search(&mut query, m),
101+
QueryResult::Descend => root.search(&mut query, m, None),
102+
QueryResult::Skip(skip) => root.search(&mut query, m, Some(skip)),
102103
_ => true,
103104
});
104105
query
@@ -212,31 +213,62 @@ impl OpTreeNode {
212213
}
213214
}
214215

215-
pub(crate) fn search<'a, 'b: 'a, Q>(&'b self, query: &mut Q, m: &OpSetMetadata) -> bool
216+
pub(crate) fn search<'a, 'b: 'a, Q>(
217+
&'b self,
218+
query: &mut Q,
219+
m: &OpSetMetadata,
220+
skip: Option<usize>,
221+
) -> bool
216222
where
217223
Q: TreeQuery<'a>,
218224
{
219225
if self.is_leaf() {
220-
for e in &self.elements {
226+
let skip = skip.unwrap_or(0);
227+
for e in self.elements.iter().skip(skip) {
221228
if query.query_element_with_metadata(e, m) == QueryResult::Finish {
222229
return true;
223230
}
224231
}
225232
false
226233
} else {
234+
let mut skip = skip.unwrap_or(0);
227235
for (child_index, child) in self.children.iter().enumerate() {
228-
match query.query_node_with_metadata(child, m) {
229-
QueryResult::Descend => {
230-
if child.search(query, m) {
231-
return true;
236+
match skip.cmp(&child.len()) {
237+
Ordering::Greater => {
238+
// not in this child at all
239+
// take off the number of elements in the child as well as the next element
240+
skip -= child.len() + 1;
241+
}
242+
Ordering::Equal => {
243+
// just try the element
244+
skip -= child.len();
245+
if let Some(e) = self.elements.get(child_index) {
246+
if query.query_element_with_metadata(e, m) == QueryResult::Finish {
247+
return true;
248+
}
232249
}
233250
}
234-
QueryResult::Finish => return true,
235-
QueryResult::Next => (),
236-
}
237-
if let Some(e) = self.elements.get(child_index) {
238-
if query.query_element_with_metadata(e, m) == QueryResult::Finish {
239-
return true;
251+
Ordering::Less => {
252+
// descend and try find it
253+
match query.query_node_with_metadata(child, m) {
254+
QueryResult::Descend => {
255+
// search in the child node, passing in the number of items left to
256+
// skip
257+
if child.search(query, m, Some(skip)) {
258+
return true;
259+
}
260+
}
261+
QueryResult::Finish => return true,
262+
QueryResult::Next => (),
263+
QueryResult::Skip(_) => panic!("had skip from non-root node"),
264+
}
265+
if let Some(e) = self.elements.get(child_index) {
266+
if query.query_element_with_metadata(e, m) == QueryResult::Finish {
267+
return true;
268+
}
269+
}
270+
// reset the skip to zero so we continue iterating normally
271+
skip = 0;
240272
}
241273
}
242274
}

automerge/src/query.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ pub(crate) trait TreeQuery<'a> {
8686
#[derive(Debug, Clone, PartialEq)]
8787
pub(crate) enum QueryResult {
8888
Next,
89+
/// Skip this many elements, only allowed from the root node.
90+
Skip(usize),
8991
Descend,
9092
Finish,
9193
}

automerge/src/query/prop.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,12 @@ impl<'a> TreeQuery<'a> for Prop<'a> {
4747
// in the root node find the first op position for the key
4848
let start = binary_search_by(child, |op| m.key_cmp(&op.key, &self.key));
4949
self.start = Some(start);
50-
QueryResult::Descend
50+
self.pos = start;
51+
QueryResult::Skip(start)
5152
}
5253
}
5354

5455
fn query_element(&mut self, op: &'a Op) -> QueryResult {
55-
// skip to our start
56-
if self.pos < self.start.unwrap() {
57-
self.pos += 1;
58-
return QueryResult::Next;
59-
}
6056
// don't bother looking at things past our key
6157
if op.key != self.key {
6258
return QueryResult::Finish;

0 commit comments

Comments
 (0)