annotate rust/hg-pyo3/src/revision.rs @ 52534:9af0330788a5

rust-pyo3: new helper for incoming iterables of revisions The pattern to borrow the core `Index` from the index proxy, and using it in `rev_pyiter_collect` is frequent enough in what remains to be converted from `hg-cpython` that it is worth having this direct helper (and it will neatly enclose the unsafety).
author Georges Racinet <georges.racinet@cloudcrane.io>
date Sat, 07 Dec 2024 14:55:42 +0100
parents a642c0a3860f
children 1b9907575768
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
52409
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
1 use pyo3::prelude::*;
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
2
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
3 use hg::revlog::RevlogIndex;
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
4 use hg::{BaseRevision, Revision, UncheckedRevision};
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
5
52534
9af0330788a5 rust-pyo3: new helper for incoming iterables of revisions
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52409
diff changeset
6 use crate::convert_cpython::proxy_index_extract;
52409
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
7 use crate::exceptions::GraphError;
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
8
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
9 /// Revision as exposed to/from the Python layer.
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
10 ///
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
11 /// We need this indirection because of the orphan rule, meaning we can't
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
12 /// implement a foreign trait (like [`cpython::ToPyObject`])
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
13 /// for a foreign type (like [`hg::UncheckedRevision`]).
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
14 ///
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
15 /// This also acts as a deterrent against blindly trusting Python to send
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
16 /// us valid revision numbers.
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
17 #[derive(
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
18 Debug,
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
19 Copy,
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
20 Clone,
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
21 PartialEq,
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
22 Eq,
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
23 PartialOrd,
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
24 Ord,
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
25 Hash,
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
26 derive_more::From,
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
27 IntoPyObject,
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
28 FromPyObject,
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
29 )]
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
30 pub struct PyRevision(pub BaseRevision);
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
31
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
32 impl From<Revision> for PyRevision {
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
33 fn from(r: Revision) -> Self {
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
34 PyRevision(r.0)
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
35 }
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
36 }
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
37
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
38 /// Utility function to convert a Python iterable into various collections
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
39 ///
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
40 /// We need this in particular
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
41 /// - because of the checked upgrade from [`PyRevision`] to [`Revision`].
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
42 /// - to feed to various methods of inner objects with `impl
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
43 /// IntoIterator<Item=Revision>` arguments, because a `PyErr` can arise at
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
44 /// each step of iteration, whereas these methods expect iterables over
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
45 /// `Revision`, not over some `Result<Revision, PyErr>`
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
46 pub fn rev_pyiter_collect<C, I>(
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
47 revs: &Bound<'_, PyAny>,
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
48 index: &I,
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
49 ) -> PyResult<C>
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
50 where
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
51 C: FromIterator<Revision>,
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
52 I: RevlogIndex,
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
53 {
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
54 rev_pyiter_collect_or_else(revs, index, |r| {
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
55 PyErr::new::<GraphError, _>(("InvalidRevision", r.0))
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
56 })
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
57 }
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
58
52534
9af0330788a5 rust-pyo3: new helper for incoming iterables of revisions
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52409
diff changeset
59 pub fn rev_pyiter_collect_with_py_index<C>(
9af0330788a5 rust-pyo3: new helper for incoming iterables of revisions
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52409
diff changeset
60 revs: &Bound<'_, PyAny>,
9af0330788a5 rust-pyo3: new helper for incoming iterables of revisions
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52409
diff changeset
61 proxy_index: &Bound<'_, PyAny>,
9af0330788a5 rust-pyo3: new helper for incoming iterables of revisions
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52409
diff changeset
62 ) -> PyResult<C>
9af0330788a5 rust-pyo3: new helper for incoming iterables of revisions
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52409
diff changeset
63 where
9af0330788a5 rust-pyo3: new helper for incoming iterables of revisions
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52409
diff changeset
64 C: FromIterator<Revision>,
9af0330788a5 rust-pyo3: new helper for incoming iterables of revisions
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52409
diff changeset
65 {
9af0330788a5 rust-pyo3: new helper for incoming iterables of revisions
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52409
diff changeset
66 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
9af0330788a5 rust-pyo3: new helper for incoming iterables of revisions
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52409
diff changeset
67 let borrowed_idx = unsafe { proxy_index_extract(proxy_index)? };
9af0330788a5 rust-pyo3: new helper for incoming iterables of revisions
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52409
diff changeset
68 rev_pyiter_collect(revs, borrowed_idx)
9af0330788a5 rust-pyo3: new helper for incoming iterables of revisions
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52409
diff changeset
69 }
9af0330788a5 rust-pyo3: new helper for incoming iterables of revisions
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52409
diff changeset
70
52409
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
71 /// Same as [`rev_pyiter_collect`], giving control on returned errors
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
72 pub fn rev_pyiter_collect_or_else<C, I>(
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
73 revs: &Bound<'_, PyAny>,
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
74 index: &I,
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
75 invalid_rev_error: impl FnOnce(PyRevision) -> PyErr + Copy,
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
76 ) -> PyResult<C>
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
77 where
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
78 C: FromIterator<Revision>,
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
79 I: RevlogIndex,
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
80 {
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
81 revs.try_iter()?
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
82 .map(|r| {
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
83 r.and_then(|o| match o.extract::<PyRevision>() {
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
84 Ok(r) => index
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
85 .check_revision(UncheckedRevision(r.0))
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
86 .ok_or_else(|| invalid_rev_error(r)),
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
87 Err(e) => Err(e),
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
88 })
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
89 })
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
90 .collect()
a642c0a3860f rust-pyo3: conversion helpers for Revision objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff changeset
91 }