annotate rust/hg-cpython/src/conversion.rs @ 50979:4c5f6e95df84

rust: make `Revision` a newtype This change is the one we've been building towards during this series. The aim is to make `Revision` mean more than a simple integer, holding the information that it is valid for a given revlog index. While this still allows for programmer error, since creating a revision directly and querying a different index with a "checked" revision are still possible, the friction created by the newtype will hopefully make us think twice about which type to use. Enough of the Rust ecosystem relies on the newtype pattern to be efficiently optimized away (even compiler in codegen testsĀ¹), so I'm not worried about this being a fundamental problem. [1] https://github.com/rust-lang/rust/blob/7a70647f195f6b0a0f1ebd72b1542ba91a32f43a/tests/codegen/vec-in-place.rs#L47
author Raphaël Gomès <rgomes@octobus.net>
date Fri, 18 Aug 2023 14:34:29 +0200
parents c7fb9b74e753
children 5a7d5fd6808c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
41240
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
1 // conversion.rs
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
2 //
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
3 // Copyright 2019 Georges Racinet <georges.racinet@octobus.net>
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
4 //
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
5 // This software may be used and distributed according to the terms of the
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
6 // GNU General Public License version 2 or any later version.
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
7
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
8 //! Bindings for the hg::ancestors module provided by the
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
9 //! `hg-core` crate. From Python, this will be seen as `rustext.ancestor`
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
10
50979
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 49631
diff changeset
11 use cpython::{ObjectProtocol, PyErr, PyObject, PyResult, Python};
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 49631
diff changeset
12 use hg::{Revision, RevlogIndex, UncheckedRevision};
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 49631
diff changeset
13
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 49631
diff changeset
14 use crate::{exceptions::GraphError, PyRevision};
41240
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
15
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
16 /// Utility function to convert a Python iterable into various collections
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
17 ///
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
18 /// We need this in particular to feed to various methods of inner objects
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
19 /// with `impl IntoIterator<Item=Revision>` arguments, because
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
20 /// a `PyErr` can arise at each step of iteration, whereas these methods
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
21 /// expect iterables over `Revision`, not over some `Result<Revision, PyErr>`
50979
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 49631
diff changeset
22 pub fn rev_pyiter_collect<C, I>(
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 49631
diff changeset
23 py: Python,
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 49631
diff changeset
24 revs: &PyObject,
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 49631
diff changeset
25 index: &I,
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 49631
diff changeset
26 ) -> PyResult<C>
41240
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
27 where
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
28 C: FromIterator<Revision>,
50979
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 49631
diff changeset
29 I: RevlogIndex,
41240
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
30 {
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
31 revs.iter(py)?
50979
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 49631
diff changeset
32 .map(|r| {
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 49631
diff changeset
33 r.and_then(|o| match o.extract::<PyRevision>(py) {
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 49631
diff changeset
34 Ok(r) => index
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 49631
diff changeset
35 .check_revision(UncheckedRevision(r.0))
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 49631
diff changeset
36 .ok_or_else(|| {
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 49631
diff changeset
37 PyErr::new::<GraphError, _>(
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 49631
diff changeset
38 py,
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 49631
diff changeset
39 ("InvalidRevision", r.0),
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 49631
diff changeset
40 )
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 49631
diff changeset
41 }),
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 49631
diff changeset
42 Err(e) => Err(e),
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 49631
diff changeset
43 })
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 49631
diff changeset
44 })
41240
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
45 .collect()
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
46 }