Mercurial > public > mercurial-scm > hg-stable
annotate rust/hg-cpython/src/lib.rs @ 50990: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 | 136aa80aa8b2 |
children | 8b7123c8947b |
rev | line source |
---|---|
40978
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
1 // lib.rs |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
2 // |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
3 // Copyright 2018 Georges Racinet <gracinet@anybox.fr> |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
4 // |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
5 // This software may be used and distributed according to the terms of the |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
6 // GNU General Public License version 2 or any later version. |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
7 |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
8 //! Python bindings of `hg-core` objects using the `cpython` crate. |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
9 //! Once compiled, the resulting single shared library object can be placed in |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
10 //! the `mercurial` package directly as `rustext.so` or `rustext.dll`. |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
11 //! It holds several modules, so that from the point of view of Python, |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
12 //! it behaves as the `cext` package. |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
13 //! |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
14 //! Example: |
41184
dcf818267bc1
rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents:
41131
diff
changeset
|
15 //! |
dcf818267bc1
rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents:
41131
diff
changeset
|
16 //! ```text |
40978
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
17 //! >>> from mercurial.rustext import ancestor |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
18 //! >>> ancestor.__doc__ |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
19 //! 'Generic DAG ancestor algorithms - Rust implementation' |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
20 //! ``` |
50005
136aa80aa8b2
rust-clippy: disable some lints crate-wide for `hg-cpython`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48930
diff
changeset
|
21 #![allow(clippy::too_many_arguments)] // rust-cpython macros |
136aa80aa8b2
rust-clippy: disable some lints crate-wide for `hg-cpython`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48930
diff
changeset
|
22 #![allow(clippy::zero_ptr)] // rust-cpython macros |
136aa80aa8b2
rust-clippy: disable some lints crate-wide for `hg-cpython`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48930
diff
changeset
|
23 #![allow(clippy::needless_update)] // rust-cpython macros |
136aa80aa8b2
rust-clippy: disable some lints crate-wide for `hg-cpython`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48930
diff
changeset
|
24 #![allow(clippy::manual_strip)] // rust-cpython macros |
136aa80aa8b2
rust-clippy: disable some lints crate-wide for `hg-cpython`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48930
diff
changeset
|
25 #![allow(clippy::type_complexity)] // rust-cpython macros |
40978
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
26 |
50990
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
27 use cpython::{FromPyObject, PyInt, Python, ToPyObject}; |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
28 use hg::{BaseRevision, Revision}; |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
29 |
42609
326fdce22fb2
rust: switch hg-core and hg-cpython to rust 2018 edition
Rapha?l Gom?s <rgomes@octobus.net>
parents:
42560
diff
changeset
|
30 /// This crate uses nested private macros, `extern crate` is still needed in |
326fdce22fb2
rust: switch hg-core and hg-cpython to rust 2018 edition
Rapha?l Gom?s <rgomes@octobus.net>
parents:
42560
diff
changeset
|
31 /// 2018 edition. |
40978
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
32 #[macro_use] |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
33 extern crate cpython; |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
34 |
41184
dcf818267bc1
rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents:
41131
diff
changeset
|
35 pub mod ancestors; |
41055
4c25038c112c
rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
40978
diff
changeset
|
36 mod cindex; |
41240
ff333620a4cc
rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents:
41184
diff
changeset
|
37 mod conversion; |
42768
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
42763
diff
changeset
|
38 #[macro_use] |
30320c7bf79f
rust-cpython: add macro for sharing references
Rapha?l Gom?s <rgomes@octobus.net>
parents:
42763
diff
changeset
|
39 pub mod ref_sharing; |
45960
50c5ee3bdf9a
copies: introduce the hg-cpython wrapper for `combine_changeset_copies`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
44541
diff
changeset
|
40 pub mod copy_tracing; |
41705
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
41240
diff
changeset
|
41 pub mod dagops; |
44541
d4f19eb471ca
rust-cpython: add `debug` module to expose debug information to Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
44222
diff
changeset
|
42 pub mod debug; |
42560
d26e4a434fe5
rust: run rfmt on all hg-core/hg-cpython code
Rapha?l Gom?s <rgomes@octobus.net>
parents:
42379
diff
changeset
|
43 pub mod dirstate; |
42217
13b64247f48f
rust-discovery: cpython bindings for the core logic
Georges Racinet <georges.racinet@octobus.net>
parents:
41705
diff
changeset
|
44 pub mod discovery; |
41184
dcf818267bc1
rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents:
41131
diff
changeset
|
45 pub mod exceptions; |
47981
8f031a274cd6
rust: Move PyBytesWithData out of copy-tracing code
Simon Sapin <simon.sapin@octobus.net>
parents:
45960
diff
changeset
|
46 mod pybytes_deref; |
43951
f98f0e3ddaa1
rust-index: add a function to convert PyObject index for hg-core
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
43289
diff
changeset
|
47 pub mod revlog; |
43251
970978975574
rust-utils: introduce a debug util to print the python stack trace
Rapha?l Gom?s <rgomes@octobus.net>
parents:
42829
diff
changeset
|
48 pub mod utils; |
40978
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
49 |
50990
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
50 /// Revision as exposed to/from the Python layer. |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
51 /// |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
52 /// We need this indirection because of the orphan rule, meaning we can't |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
53 /// implement a foreign trait (like [`cpython::ToPyObject`]) |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
54 /// for a foreign type (like [`hg::UncheckedRevision`]). |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
55 /// |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
56 /// This also acts as a deterrent against blindly trusting Python to send |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
57 /// us valid revision numbers. |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
58 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
59 pub struct PyRevision(BaseRevision); |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
60 |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
61 impl From<Revision> for PyRevision { |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
62 fn from(r: Revision) -> Self { |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
63 PyRevision(r.0) |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
64 } |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
65 } |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
66 |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
67 impl<'s> FromPyObject<'s> for PyRevision { |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
68 fn extract( |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
69 py: Python, |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
70 obj: &'s cpython::PyObject, |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
71 ) -> cpython::PyResult<Self> { |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
72 Ok(Self(obj.extract::<BaseRevision>(py)?)) |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
73 } |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
74 } |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
75 |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
76 impl ToPyObject for PyRevision { |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
77 type ObjectType = PyInt; |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
78 |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
79 fn to_py_object(&self, py: Python) -> Self::ObjectType { |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
80 self.0.to_py_object(py) |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
81 } |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
82 } |
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50005
diff
changeset
|
83 |
40978
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
84 py_module_initializer!(rustext, initrustext, PyInit_rustext, |py, m| { |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
85 m.add( |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
86 py, |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
87 "__doc__", |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
88 "Mercurial core concepts - Rust implementation", |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
89 )?; |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
90 |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
91 let dotted_name: String = m.get(py, "__name__")?.extract(py)?; |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
92 m.add(py, "ancestor", ancestors::init_module(py, &dotted_name)?)?; |
41705
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
41240
diff
changeset
|
93 m.add(py, "dagop", dagops::init_module(py, &dotted_name)?)?; |
44541
d4f19eb471ca
rust-cpython: add `debug` module to expose debug information to Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
44222
diff
changeset
|
94 m.add(py, "debug", debug::init_module(py, &dotted_name)?)?; |
45960
50c5ee3bdf9a
copies: introduce the hg-cpython wrapper for `combine_changeset_copies`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
44541
diff
changeset
|
95 m.add( |
50c5ee3bdf9a
copies: introduce the hg-cpython wrapper for `combine_changeset_copies`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
44541
diff
changeset
|
96 py, |
50c5ee3bdf9a
copies: introduce the hg-cpython wrapper for `combine_changeset_copies`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
44541
diff
changeset
|
97 "copy_tracing", |
50c5ee3bdf9a
copies: introduce the hg-cpython wrapper for `combine_changeset_copies`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
44541
diff
changeset
|
98 copy_tracing::init_module(py, &dotted_name)?, |
50c5ee3bdf9a
copies: introduce the hg-cpython wrapper for `combine_changeset_copies`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
44541
diff
changeset
|
99 )?; |
42217
13b64247f48f
rust-discovery: cpython bindings for the core logic
Georges Racinet <georges.racinet@octobus.net>
parents:
41705
diff
changeset
|
100 m.add(py, "discovery", discovery::init_module(py, &dotted_name)?)?; |
42330
e240bec26626
rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
42217
diff
changeset
|
101 m.add(py, "dirstate", dirstate::init_module(py, &dotted_name)?)?; |
43966
b69d5f3a41d0
rust-index: add a struct wrapping the C index
Georges Racinet <georges.racinet@octobus.net>
parents:
43951
diff
changeset
|
102 m.add(py, "revlog", revlog::init_module(py, &dotted_name)?)?; |
40978
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
103 m.add(py, "GraphError", py.get_type::<exceptions::GraphError>())?; |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
104 Ok(()) |
5532823e8c18
rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff
changeset
|
105 }); |
43289
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43251
diff
changeset
|
106 |
48930
7b068abe4aa2
rust: jettison Python 2 support
Augie Fackler <augie@google.com>
parents:
48042
diff
changeset
|
107 #[cfg(not(feature = "python3-bin"))] |
43289
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43251
diff
changeset
|
108 #[test] |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43251
diff
changeset
|
109 #[ignore] |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43251
diff
changeset
|
110 fn libpython_must_be_linked_to_run_tests() { |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43251
diff
changeset
|
111 // stub function to tell that some tests wouldn't run |
8d432d3a2d7c
rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents:
43251
diff
changeset
|
112 } |