[PATCH 1 of 5 RFC] rust: pure Rust lazyancestors iterator

Yuya Nishihara yuya at tcha.org
Sat Sep 29 23:46:10 EDT 2018


On Fri, 28 Sep 2018 15:31:08 +0200, Georges Racinet wrote:
> # HG changeset patch
> # User Georges Racinet <gracinet at anybox.fr>
> # Date 1538060596 -7200
> #      Thu Sep 27 17:03:16 2018 +0200
> # Node ID d8c9571755a64e1fc3429587dfd3949b9862eceb
> # Parent  d3d4b4b5f725124ef9e93cf74d779a7a05aa11b7
> # EXP-Topic rustancestors-rfc
> rust: pure Rust lazyancestors iterator

First, thanks for tackling on the oxidization plain. I've quickly scanned
a first few patches, and I'm generally positive to these.

Here's random thoughts regarding the project/module layout:

 - place pure Rust code under rust/ ?

   I think that's the intention why we have the rust/ tree. Perhaps, the
   pure Rust modules can be packaged into a crate (e.g. hg-core), and the
   Rust FFI part will depend on it (e.g. hg-ffi).

   And the compiled CPython module (and maybe source) will be placed at
   mercurial/rust.

 - HGMODULEPOLICY=rust

   Perhaps, we'll want a separate policy to enable the Rust bindings.
   Most of the unimplemented functions will be forwarded to cext, just like
   the cffi -> pure fallback.

> +impl<G: Graph> AncestorsIterator<G> {
> +    /// Constructor.
> +    ///
> +    /// We actually expect initrevs to be i64, and we coerce them to the
> +    /// i32 of our internal representations. The reason is that from C
> +    /// code, they actually come as such.
> +    /// Here it would be better to take any iterable over our internal
> +    /// revision numbers, and have the conversion be made from the caller.
> +    pub fn new(
> +        graph: G,
> +        initrevs: &Vec<i64>,
> +        stoprev: i64,
> +        inclusive: bool,
> +    ) -> Self {
> +        let stop32 = stoprev as i32;
> +        // because in iteration, contrary to what happens in ancestor.py, we
> +        // compare with stoprev before pushing, we have to prefilter in the
> +        // constructor too.
> +        let deref_filter = initrevs.iter()
> +            .map(|&x| x as i32).filter(|x| stop32 <= *x);

Nit: I think i64->i32 conversion should be done by the caller. The initrevs
argument can be IntoIterator<Item = i32> instead.

> +    #[inline]
> +    fn conditionally_push_rev(&mut self, rev: i32) {
> +        if self.stoprev <= rev && !self.seen.contains(&rev) {
> +            self.seen.insert(rev);
> +            self.visit.push(rev);

We could eliminate the seen set by skipping duplicated revisions in next().
It's theoretically slower and was actually slower in Python, but might be
worth trying in Rust.


More information about the Mercurial-devel mailing list