annotate rust/hg-core/src/ancestors.rs @ 40300:72b94f946e90

rust: rustlazyancestors.__contains__ This changeset provides a Rust implementation of the iteration performed by lazyancestor.__contains__ It has the advantage over the Python iteration to use the 'seen' set encapsuled into the dedicated iterator (self._containsiter), rather than storing emitted items in another set (self._containsseen), and hence should reduce the memory footprint. Also, there's no need to convert intermediate emitted revisions back into Python integers. At this point, it would be tempting to implement the whole lazyancestor object in Rust, but that would lead to more C wrapping code (two objects) for little expected benefits.
author Georges Racinet <gracinet@anybox.fr>
date Mon, 08 Oct 2018 19:11:41 +0200
parents dbc28c91f7ff
children e13ab4acf555
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
1 // ancestors.rs
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
2 //
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
3 // Copyright 2018 Georges Racinet <gracinet@anybox.fr>
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
4 //
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
5 // This software may be used and distributed according to the terms of the
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
6 // GNU General Public License version 2 or any later version.
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
7
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
8 //! Rust versions of generic DAG ancestors algorithms for Mercurial
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
9
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
10 use super::{Graph, GraphError, Revision, NULL_REVISION};
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
11 use std::collections::{BinaryHeap, HashSet};
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
12
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
13 /// Iterator over the ancestors of a given list of revisions
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
14 /// This is a generic type, defined and implemented for any Graph, so that
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
15 /// it's easy to
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
16 ///
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
17 /// - unit test in pure Rust
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
18 /// - bind to main Mercurial code, potentially in several ways and have these
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
19 /// bindings evolve over time
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
20 pub struct AncestorsIterator<G: Graph> {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
21 graph: G,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
22 visit: BinaryHeap<Revision>,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
23 seen: HashSet<Revision>,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
24 stoprev: Revision,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
25 }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
26
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
27 impl<G: Graph> AncestorsIterator<G> {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
28 /// Constructor.
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
29 ///
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
30 /// if `inclusive` is true, then the init revisions are emitted in
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
31 /// particular, otherwise iteration starts from their parents.
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
32 pub fn new<I>(
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
33 graph: G,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
34 initrevs: I,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
35 stoprev: Revision,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
36 inclusive: bool,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
37 ) -> Result<Self, GraphError>
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
38 where
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
39 I: IntoIterator<Item = Revision>,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
40 {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
41 let filtered_initrevs = initrevs.into_iter().filter(|&r| r >= stoprev);
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
42 if inclusive {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
43 let visit: BinaryHeap<Revision> = filtered_initrevs.collect();
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
44 let seen = visit.iter().map(|&x| x).collect();
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
45 return Ok(AncestorsIterator {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
46 visit: visit,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
47 seen: seen,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
48 stoprev: stoprev,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
49 graph: graph,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
50 });
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
51 }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
52 let mut this = AncestorsIterator {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
53 visit: BinaryHeap::new(),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
54 seen: HashSet::new(),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
55 stoprev: stoprev,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
56 graph: graph,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
57 };
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
58 this.seen.insert(NULL_REVISION);
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
59 for rev in filtered_initrevs {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
60 this.conditionally_push_parents(rev)?;
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
61 }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
62 Ok(this)
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
63 }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
64
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
65 #[inline]
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
66 fn conditionally_push_rev(&mut self, rev: Revision) {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
67 if self.stoprev <= rev && !self.seen.contains(&rev) {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
68 self.seen.insert(rev);
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
69 self.visit.push(rev);
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
70 }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
71 }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
72
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
73 #[inline]
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
74 fn conditionally_push_parents(
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
75 &mut self,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
76 rev: Revision,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
77 ) -> Result<(), GraphError> {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
78 let parents = self.graph.parents(rev)?;
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
79 self.conditionally_push_rev(parents.0);
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
80 self.conditionally_push_rev(parents.1);
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
81 Ok(())
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
82 }
40300
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
83
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
84 /// Consumes partially the iterator to tell if the given target
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
85 /// revision
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
86 /// is in the ancestors it emits.
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
87 /// This is meant for iterators actually dedicated to that kind of
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
88 /// purpose
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
89 pub fn contains(&mut self, target: Revision) -> bool {
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
90 if self.seen.contains(&target) && target != NULL_REVISION {
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
91 return true;
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
92 }
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
93 for rev in self {
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
94 if rev == target {
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
95 return true;
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
96 }
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
97 if rev < target {
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
98 return false;
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
99 }
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
100 }
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
101 false
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
102 }
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
103 }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
104
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
105 /// Main implementation.
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
106 ///
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
107 /// The algorithm is the same as in `_lazyancestorsiter()` from `ancestors.py`
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
108 /// with a few non crucial differences:
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
109 ///
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
110 /// - there's no filtering of invalid parent revisions. Actually, it should be
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
111 /// consistent and more efficient to filter them from the end caller.
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
112 /// - we don't use the equivalent of `heapq.heapreplace()`, but we should, for
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
113 /// the same reasons (using `peek_mut`)
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
114 /// - we don't have the optimization for adjacent revs (case where p1 == rev-1)
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
115 /// - we save a few pushes by comparing with `stoprev` before pushing
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
116 ///
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
117 /// Error treatment:
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
118 /// We swallow the possible GraphError of conditionally_push_parents() to
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
119 /// respect the Iterator trait in a simple manner: never emitting parents
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
120 /// for the returned revision. We finds this good enough for now, because:
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
121 ///
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
122 /// - there's a good chance that invalid revisionss are fed from the start,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
123 /// and `new()` doesn't swallow the error result.
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
124 /// - this is probably what the Python implementation produces anyway, due
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
125 /// to filtering at each step, and Python code is currently the only
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
126 /// concrete caller we target, so we shouldn't need a finer error treatment
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
127 /// for the time being.
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
128 impl<G: Graph> Iterator for AncestorsIterator<G> {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
129 type Item = Revision;
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
130
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
131 fn next(&mut self) -> Option<Revision> {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
132 let current = match self.visit.pop() {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
133 None => {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
134 return None;
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
135 }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
136 Some(i) => i,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
137 };
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
138 self.conditionally_push_parents(current).unwrap_or(());
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
139 Some(current)
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
140 }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
141 }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
142
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
143 #[cfg(test)]
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
144 mod tests {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
145
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
146 use super::*;
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
147
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
148 #[derive(Clone, Debug)]
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
149 struct Stub;
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
150
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
151 /// This is the same as the dict from test-ancestors.py
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
152 impl Graph for Stub {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
153 fn parents(
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
154 &self,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
155 rev: Revision,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
156 ) -> Result<(Revision, Revision), GraphError> {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
157 match rev {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
158 0 => Ok((-1, -1)),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
159 1 => Ok((0, -1)),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
160 2 => Ok((1, -1)),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
161 3 => Ok((1, -1)),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
162 4 => Ok((2, -1)),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
163 5 => Ok((4, -1)),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
164 6 => Ok((4, -1)),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
165 7 => Ok((4, -1)),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
166 8 => Ok((-1, -1)),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
167 9 => Ok((6, 7)),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
168 10 => Ok((5, -1)),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
169 11 => Ok((3, 7)),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
170 12 => Ok((9, -1)),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
171 13 => Ok((8, -1)),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
172 r => Err(GraphError::ParentOutOfRange(r)),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
173 }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
174 }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
175 }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
176
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
177 fn list_ancestors<G: Graph>(
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
178 graph: G,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
179 initrevs: Vec<Revision>,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
180 stoprev: Revision,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
181 inclusive: bool,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
182 ) -> Vec<Revision> {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
183 AncestorsIterator::new(graph, initrevs, stoprev, inclusive)
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
184 .unwrap()
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
185 .collect()
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
186 }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
187
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
188 #[test]
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
189 /// Same tests as test-ancestor.py, without membership
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
190 /// (see also test-ancestor.py.out)
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
191 fn test_list_ancestor() {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
192 assert_eq!(list_ancestors(Stub, vec![], 0, false), vec![]);
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
193 assert_eq!(
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
194 list_ancestors(Stub, vec![11, 13], 0, false),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
195 vec![8, 7, 4, 3, 2, 1, 0]
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
196 );
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
197 assert_eq!(list_ancestors(Stub, vec![1, 3], 0, false), vec![1, 0]);
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
198 assert_eq!(
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
199 list_ancestors(Stub, vec![11, 13], 0, true),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
200 vec![13, 11, 8, 7, 4, 3, 2, 1, 0]
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
201 );
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
202 assert_eq!(list_ancestors(Stub, vec![11, 13], 6, false), vec![8, 7]);
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
203 assert_eq!(
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
204 list_ancestors(Stub, vec![11, 13], 6, true),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
205 vec![13, 11, 8, 7]
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
206 );
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
207 assert_eq!(list_ancestors(Stub, vec![11, 13], 11, true), vec![13, 11]);
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
208 assert_eq!(list_ancestors(Stub, vec![11, 13], 12, true), vec![13]);
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
209 assert_eq!(
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
210 list_ancestors(Stub, vec![10, 1], 0, true),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
211 vec![10, 5, 4, 2, 1, 0]
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
212 );
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
213 }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
214
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
215 #[test]
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
216 /// Corner case that's not directly in test-ancestors.py, but
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
217 /// that happens quite often, as demonstrated by running the whole
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
218 /// suite.
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
219 /// For instance, run tests/test-obsolete-checkheads.t
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
220 fn test_nullrev_input() {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
221 let mut iter =
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
222 AncestorsIterator::new(Stub, vec![-1], 0, false).unwrap();
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
223 assert_eq!(iter.next(), None)
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
224 }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
225
40300
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
226 #[test]
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
227 fn test_contains() {
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
228 let mut lazy =
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
229 AncestorsIterator::new(Stub, vec![10, 1], 0, true).unwrap();
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
230 assert!(lazy.contains(1));
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
231 assert!(!lazy.contains(3));
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
232
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
233 let mut lazy =
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
234 AncestorsIterator::new(Stub, vec![0], 0, false).unwrap();
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
235 assert!(!lazy.contains(NULL_REVISION));
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
236 }
72b94f946e90 rust: rustlazyancestors.__contains__
Georges Racinet <gracinet@anybox.fr>
parents: 40271
diff changeset
237
40271
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
238 /// A corrupted Graph, supporting error handling tests
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
239 struct Corrupted;
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
240
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
241 impl Graph for Corrupted {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
242 fn parents(
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
243 &self,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
244 rev: Revision,
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
245 ) -> Result<(Revision, Revision), GraphError> {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
246 match rev {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
247 1 => Ok((0, -1)),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
248 r => Err(GraphError::ParentOutOfRange(r)),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
249 }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
250 }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
251 }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
252
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
253 #[test]
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
254 fn test_initrev_out_of_range() {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
255 // inclusive=false looks up initrev's parents right away
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
256 match AncestorsIterator::new(Stub, vec![25], 0, false) {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
257 Ok(_) => panic!("Should have been ParentOutOfRange"),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
258 Err(e) => assert_eq!(e, GraphError::ParentOutOfRange(25)),
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
259 }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
260 }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
261
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
262 #[test]
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
263 fn test_next_out_of_range() {
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
264 // inclusive=false looks up initrev's parents right away
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
265 let mut iter =
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
266 AncestorsIterator::new(Corrupted, vec![1], 0, false).unwrap();
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
267 assert_eq!(iter.next(), Some(0));
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
268 assert_eq!(iter.next(), None);
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
269 }
dbc28c91f7ff rust: pure Rust lazyancestors iterator
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
270 }