annotate rust/pyo3-sharedref/src/lib.rs @ 52991:d7174b43f3e6

typing: fix the signature of `treemanifest.fastdelta()` We're still missing a few explicit bits of Protocol subclassing, and pytype found this when the subclassing is applied. So fix this first.
author Matt Harbison <matt_harbison@yahoo.com>
date Tue, 17 Dec 2024 19:29:08 -0500
parents 8f6d25439bdc
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
1 // Copyright (c) 2019 Raphaël Gomès <rgomes@octobus.net>,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
2 // Yuya Nishihara <yuya@tcha.org>
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
3 // 2024 Georges Racinet <georges.racinet@cloudcrane.io>
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
4 //
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
6 // of this software and associated documentation files (the "Software"), to
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
7 // deal in the Software without restriction, including without limitation the
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
8 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
9 // sell copies of the Software, and to permit persons to whom the Software is
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
10 // furnished to do so, subject to the following conditions:
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
11 //
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
12 // The above copyright notice and this permission notice shall be included in
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
13 // all copies or substantial portions of the Software.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
14 //
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
21 // IN THE SOFTWARE.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
22
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
23 //! Utility to share Rust reference across Python objects.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
24
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
25 use pyo3::exceptions::PyRuntimeError;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
26 use pyo3::prelude::*;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
27
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
28 use std::ops::{Deref, DerefMut};
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
29 use std::sync::atomic::{AtomicUsize, Ordering};
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
30 use std::sync::{
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
31 RwLock, RwLockReadGuard, RwLockWriteGuard, TryLockError, TryLockResult,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
32 };
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
33
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
34 /// A mutable memory location shareable immutably across Python objects.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
35 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
36 /// This data structure is meant to be used as a field in a Python class
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
37 /// definition.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
38 /// It provides interior mutability in a way that allows it to be immutably
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
39 /// referenced by other Python objects defined in Rust than its owner, in
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
40 /// a more general form than references to the whole data.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
41 /// These immutable references are stored in the referencing Python objects as
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
42 /// [`SharedByPyObject`] fields.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
43 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
44 /// The primary use case is to implement a Python iterator over a Rust
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
45 /// iterator: since a Python object cannot hold a lifetime-bound object,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
46 /// `Iter<'a, T>` cannot be a data field of the Python iterator object.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
47 /// While `&'a T` can be replaced with [`std::sync::Arc`], this is typically
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
48 /// not suited for more complex objects that are created from such references
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
49 /// and re-expose the lifetime on their types, such as iterators.
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
50 /// The [`PyShareableRef::share_immutable()`] and
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
51 /// [`SharedByPyObject::map()`] methods provide a way around this issue.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
52 ///
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
53 /// [`PyShareable`] is [`Sync`]. It works internally with locks and
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
54 /// a "generation" counter that keeps track of mutations.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
55 ///
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
56 /// [`PyShareable`] is merely a data struct to be stored in its
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
57 /// owner Python object.
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
58 /// Any further operation will be performed through [`PyShareableRef`], which
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
59 /// is a lifetime-bound reference to the [`PyShareable`].
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
60 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
61 /// # Example
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
62 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
63 /// ```
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
64 /// use pyo3::prelude::*;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
65 /// use pyo3_sharedref::*;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
66 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
67 /// use pyo3::ffi::c_str;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
68 /// use pyo3::types::PyDictMethods;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
69 /// use pyo3::types::{PyDict, PyTuple};
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
70 /// use std::collections::{hash_set::Iter as IterHashSet, HashSet};
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
71 /// use pyo3::exceptions::PyRuntimeError;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
72 /// use std::ffi::CStr;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
73 /// use std::vec::Vec;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
74 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
75 /// #[pyclass(sequence)]
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
76 /// struct Set {
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
77 /// rust_set: PyShareable<HashSet<i32>>,
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
78 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
79 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
80 /// #[pymethods]
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
81 /// impl Set {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
82 /// #[new]
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
83 /// fn new(values: &Bound<'_, PyTuple>) -> PyResult<Self> {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
84 /// let as_vec = values.extract::<Vec<i32>>()?;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
85 /// let s: HashSet<_> = as_vec.iter().copied().collect();
52633
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52631
diff changeset
86 /// Ok(Self { rust_set: s.into() })
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
87 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
88 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
89 /// fn __iter__(slf: &Bound<'_, Self>) -> SetIterator {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
90 /// SetIterator::new(slf)
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
91 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
92 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
93 /// fn add(slf: &Bound<'_, Self>, i: i32) -> PyResult<()> {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
94 /// let rust_set = &slf.borrow().rust_set;
52633
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52631
diff changeset
95 /// let shared_ref = unsafe { rust_set.borrow_with_owner(slf) };
52634
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
96 /// let mut set_ref = shared_ref.write();
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
97 /// set_ref.insert(i);
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
98 /// Ok(())
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
99 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
100 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
101 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
102 /// #[pyclass]
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
103 /// struct SetIterator {
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
104 /// rust_iter: SharedByPyObject<IterHashSet<'static, i32>>,
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
105 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
106 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
107 /// #[pymethods]
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
108 /// impl SetIterator {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
109 /// #[new]
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
110 /// fn new(s: &Bound<'_, Set>) -> Self {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
111 /// let py = s.py();
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
112 /// let rust_set = &s.borrow().rust_set;
52637
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
113 /// let iter = unsafe { rust_set.share_map(s, |o| o.iter()) };
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
114 /// Self {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
115 /// rust_iter: iter.into(),
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
116 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
117 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
118 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
119 /// fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
120 /// slf
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
121 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
122 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
123 /// fn __next__(mut slf: PyRefMut<'_, Self>) -> PyResult<Option<i32>> {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
124 /// let py = slf.py();
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
125 /// let shared = &mut slf.rust_iter;
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
126 /// let mut inner = unsafe { shared.try_borrow_mut(py) }?;
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
127 /// Ok(inner.next().copied())
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
128 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
129 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
130 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
131 /// /// a shortcut similar to `[pyo3::py_run!]`, allowing inspection of PyErr
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
132 /// fn py_run(statement: &CStr, locals: &Bound<'_, PyDict>) -> PyResult<()> {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
133 /// locals.py().run(statement, None, Some(locals))
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
134 /// }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
135 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
136 /// # pyo3::prepare_freethreaded_python();
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
137 /// Python::with_gil(|py| {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
138 /// let tuple = PyTuple::new(py, vec![2, 1, 2])?;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
139 /// let set = Bound::new(py, Set::new(&tuple)?)?;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
140 /// let iter = Bound::new(py, Set::__iter__(&set))?;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
141 /// let locals = PyDict::new(py);
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
142 /// locals.set_item("rust_set", set).unwrap();
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
143 /// locals.set_item("rust_iter", iter).unwrap();
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
144 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
145 /// /// iterating on our Rust set just works
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
146 /// py_run(
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
147 /// c_str!("assert sorted(i for i in rust_iter) == [1, 2]"),
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
148 /// &locals,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
149 /// )?;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
150 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
151 /// /// however, if any mutation occurs on the Rust set, the iterator
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
152 /// /// becomes invalid. Attempts to use it raise `RuntimeError`.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
153 /// py_run(c_str!("rust_set.add(3)"), &locals)?;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
154 /// let err = py_run(c_str!("next(rust_iter)"), &locals).unwrap_err();
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
155 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
156 /// let exc_repr = format!("{:?}", err.value(py));
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
157 /// assert_eq!(
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
158 /// exc_repr,
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
159 /// "RuntimeError('Cannot access to shared reference after mutation')"
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
160 /// );
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
161 /// # Ok::<(), PyErr>(())
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
162 /// })
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
163 /// # .expect("This example should not return an error");
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
164 /// ```
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
165 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
166 /// The borrow rules are enforced dynamically in a similar manner to the
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
167 /// Python iterator.
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
168 ///
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
169 /// [`PyShareable`] is merely a data struct to be stored in a Python object.
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
170 /// Any further operation will be performed through [PyShareableRef], which is
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
171 /// a lifetime-bound reference to the [`PyShareable`].
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
172 #[derive(Debug)]
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
173 pub struct PyShareable<T: ?Sized> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
174 state: PySharedState,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
175 data: RwLock<T>,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
176 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
177
52637
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
178 impl<T: 'static> PyShareable<T> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
179 /// Borrows the shared data and its state, keeping a reference
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
180 /// on the owner Python object.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
181 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
182 /// # Safety
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
183 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
184 /// The `data` must be owned by the `owner`. Otherwise, calling
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
185 /// `share_immutable()` on the shared ref would create an invalid
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
186 /// reference.
52633
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52631
diff changeset
187 pub unsafe fn borrow_with_owner<'py>(
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
188 &'py self,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
189 owner: &'py Bound<'py, PyAny>,
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
190 ) -> PyShareableRef<'py, T> {
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
191 PyShareableRef {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
192 owner,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
193 state: &self.state,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
194 data: &self.data,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
195 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
196 }
52637
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
197
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
198 /// Share for other Python objects
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
199 ///
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
200 /// # Safety
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
201 ///
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
202 /// The `data` must be owned by the `owner`. Otherwise, the resulting
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
203 /// [`SharedByPyObject`] would contain an invalid reference.
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
204 pub unsafe fn share<'py>(
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
205 &'py self,
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
206 owner: &'py Bound<'py, PyAny>,
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
207 ) -> SharedByPyObject<&'static T> {
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
208 self.borrow_with_owner(owner).share_immutable()
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
209 }
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
210
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
211 /// Share for other Python objects, transforming the inner data
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
212 /// with a closure
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
213 ///
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
214 /// # Safety
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
215 ///
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
216 /// The `data` must be owned by the `owner`. Otherwise, the resulting
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
217 /// [`SharedByPyObject`] would contain an invalid reference.
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
218 pub unsafe fn share_map<'py, U>(
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
219 &'py self,
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
220 owner: &'py Bound<'py, PyAny>,
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
221 f: impl FnOnce(&'static T) -> U,
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
222 ) -> SharedByPyObject<U> {
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
223 self.share(owner).map(owner.py(), f)
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
224 }
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
225
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
226 /// # Safety
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
227 ///
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
228 /// The `data` must be owned by the `owner`. Otherwise, the resulting
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
229 /// [`SharedByPyObject`] would contain an invalid reference.
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
230 pub unsafe fn try_share<'py>(
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
231 &'py self,
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
232 owner: &'py Bound<'py, PyAny>,
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
233 ) -> Result<SharedByPyObject<&'static T>, TryShareError> {
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
234 self.borrow_with_owner(owner).try_share_immutable()
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
235 }
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
236
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
237 /// # Safety
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
238 ///
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
239 /// The `data` must be owned by the `owner`. Otherwise, the resulting
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
240 /// [`SharedByPyObject`] would contain an invalid reference.
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
241 pub unsafe fn try_share_map<'py, U>(
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
242 &'py self,
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
243 owner: &'py Bound<'py, PyAny>,
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
244 f: impl FnOnce(&'static T) -> U,
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
245 ) -> Result<SharedByPyObject<U>, TryShareError> {
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
246 Ok(self.try_share(owner)?.map(owner.py(), f))
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52636
diff changeset
247 }
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
248 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
249
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
250 impl<T> From<T> for PyShareable<T> {
52633
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52631
diff changeset
251 fn from(value: T) -> Self {
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52631
diff changeset
252 Self {
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52631
diff changeset
253 state: PySharedState::new(),
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52631
diff changeset
254 data: value.into(),
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52631
diff changeset
255 }
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52631
diff changeset
256 }
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52631
diff changeset
257 }
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52631
diff changeset
258
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
259 /// Errors that can happen in `share_immutable()`
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
260 #[derive(Debug, PartialEq, Eq)]
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
261 pub enum TryShareError {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
262 /// The inner lock is poisoned and we do not want to implement recovery
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
263 InnerLockPoisoned,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
264 /// The inner lock would block and we are expecting to take it immediately
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
265 InnerLockWouldBlock,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
266 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
267
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
268 impl<T> From<TryLockError<T>> for TryShareError {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
269 fn from(e: TryLockError<T>) -> Self {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
270 match e {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
271 TryLockError::Poisoned(_) => Self::InnerLockPoisoned,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
272 TryLockError::WouldBlock => Self::InnerLockWouldBlock,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
273 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
274 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
275 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
276
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
277 /// A reference to [`PyShareable`] and its legit owner Python object.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
278 ///
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
279 /// This is a lifetime-bound reference to the [PyShareable] data field,
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
280 /// and could be created by an automatically generated accessor when
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
281 /// we make one.
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
282 pub struct PyShareableRef<'py, T: 'py + ?Sized> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
283 owner: &'py Bound<'py, PyAny>,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
284 state: &'py PySharedState,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
285 data: &'py RwLock<T>, // TODO perhaps this needs Pin
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
286 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
287
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
288 impl<'py, T: ?Sized> PyShareableRef<'py, T> {
52634
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
289 /// Take the lock on the wrapped value for read-only operations.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
290 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
291 /// # Panics
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
292 ///
52634
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
293 /// Panics if the lock is currently held for write operations.
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
294 pub fn read(&self) -> RwLockReadGuard<'py, T> {
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
295 self.try_read().expect("already mutably borrowed")
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
296 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
297
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
298 /// Immutably borrows the wrapped value, returning an error if the value
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
299 /// is currently mutably borrowed.
52634
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
300 pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<'py, T>> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
301 // state isn't involved since
52634
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
302 // - data.try_read() would fail if self is mutably borrowed,
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
303 // - and data.try_write() would fail while self is borrowed.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
304 self.data.try_read()
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
305 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
306
52634
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
307 /// Take the lock on the wrapped value for write operations.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
308 ///
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
309 /// Any existing shared references will be invalidated.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
310 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
311 /// # Panics
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
312 ///
52634
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
313 /// Panics if the lock is currently held.
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
314 pub fn write(&self) -> RwLockWriteGuard<'py, T> {
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
315 self.try_write().expect("already borrowed")
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
316 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
317
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
318 /// Mutably borrows the wrapped value, returning an error if the value
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
319 /// is currently borrowed.
52634
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
320 pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<'py, T>> {
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
321 // the value may be immutably borrowed through SharedByPyObject
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
322 if self.state.current_borrow_count(self.py()) > 0 {
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
323 // propagate borrow-by-shared state to data to get BorrowMutError
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
324 let _dummy = self.data.read();
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
325 let _unused = self.data.try_write()?;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
326 unreachable!("BorrowMutError should have been returned");
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
327 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
328
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
329 let data_ref = self.data.try_write()?;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
330 self.state.increment_generation(self.py());
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
331 Ok(data_ref)
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
332 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
333
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
334 /// Creates an immutable reference which is not bound to lifetime.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
335 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
336 /// # Panics
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
337 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
338 /// Panics if the value is currently mutably borrowed.
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
339 pub fn share_immutable(&self) -> SharedByPyObject<&'static T> {
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
340 self.try_share_immutable()
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
341 .expect("already mutably borrowed")
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
342 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
343
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
344 /// Creates an immutable reference which is not bound to lifetime,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
345 /// returning an error if the value is currently mutably borrowed.
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
346 pub fn try_share_immutable(
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
347 &self,
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
348 ) -> Result<SharedByPyObject<&'static T>, TryShareError> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
349 // make sure self.data isn't mutably borrowed; otherwise the
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
350 // generation number wouldn't be trusted.
52634
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
351 let data_ref = self.try_read()?;
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
352
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
353 // keep reference to the owner so the data and state are alive,
52634
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52633
diff changeset
354 // but the data pointer can be invalidated by write().
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
355 // the state wouldn't since it is immutable.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
356 let state_ptr: *const PySharedState = self.state;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
357 let data_ptr: *const T = &*data_ref;
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
358 Ok(SharedByPyObject::<&'static T> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
359 owner: self.owner.clone().unbind(),
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
360 state: unsafe { &*state_ptr },
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
361 generation: self.state.current_generation(self.py()),
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
362 data: unsafe { &*data_ptr },
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
363 })
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
364 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
365
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
366 /// Retrieve the GIL handle
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
367 fn py(&self) -> Python<'py> {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
368 // Since this is a smart pointer implying the GIL lifetime,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
369 // we might as well use `assume_gil_acquired`, but the method
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
370 // of `Bound` does it for us.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
371 self.owner.py()
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
372 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
373 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
374
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
375 /// The shared state between Python and Rust
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
376 ///
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
377 /// `PySharedState` is owned by `PyShareable`, and is shared across its
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
378 /// derived references. The consistency of these references are guaranteed
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
379 /// as follows:
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
380 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
381 /// - The immutability of `PycCass` object fields. Any mutation of
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
382 /// [`PyShareable`] is allowed only through its `write()`.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
383 /// - The `py: Python<'_>` token, which makes sure that any data access is
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
384 /// synchronized by the GIL.
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
385 /// - The underlying `RefCell`, which prevents `PyShareable` value from being
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
386 /// directly borrowed or shared while it is mutably borrowed.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
387 /// - The `borrow_count`, which is the number of references borrowed from
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
388 /// `SharedByPyObject`. Just like `RefCell`, mutation is prohibited while
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
389 /// `SharedByPyObject` is borrowed.
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
390 /// - The `generation` counter, which increments on `write()`.
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
391 /// `SharedByPyObject`
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
392 #[derive(Debug)]
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
393 struct PySharedState {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
394 // The counter variable could be Cell<usize> since any operation on
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
395 // PySharedState is synchronized by the GIL, but being "atomic" makes
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
396 // PySharedState inherently Sync. The ordering requirement doesn't
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
397 // matter thanks to the GIL. That's why Ordering::Relaxed is used
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
398 // everywhere.
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
399 /// The number of immutable references borrowed through shared reference.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
400 borrow_count: AtomicUsize,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
401 /// The mutation counter of the underlying value.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
402 generation: AtomicUsize,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
403 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
404
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
405 impl PySharedState {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
406 const fn new() -> PySharedState {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
407 PySharedState {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
408 borrow_count: AtomicUsize::new(0),
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
409 generation: AtomicUsize::new(0),
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
410 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
411 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
412
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
413 fn current_borrow_count(&self, _py: Python) -> usize {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
414 self.borrow_count.load(Ordering::Relaxed)
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
415 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
416
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
417 fn increase_borrow_count(&self, _py: Python) {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
418 // this wraps around if there are more than usize::MAX borrowed
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
419 // references, which shouldn't happen due to memory limit.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
420 self.borrow_count.fetch_add(1, Ordering::Relaxed);
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
421 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
422
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
423 fn decrease_borrow_count(&self, _py: Python) {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
424 let prev_count = self.borrow_count.fetch_sub(1, Ordering::Relaxed);
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
425 assert!(prev_count > 0);
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
426 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
427
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
428 fn current_generation(&self, _py: Python) -> usize {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
429 self.generation.load(Ordering::Relaxed)
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
430 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
431
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
432 fn increment_generation(&self, py: Python) {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
433 assert_eq!(self.current_borrow_count(py), 0);
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
434 // this wraps around to the same value if mutably borrowed
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
435 // usize::MAX times, which wouldn't happen in practice.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
436 self.generation.fetch_add(1, Ordering::Relaxed);
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
437 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
438 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
439
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
440 /// Helper to keep the borrow count updated while the shared object is
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
441 /// immutably borrowed without using the `RwLock` interface.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
442 struct BorrowPyShared<'a> {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
443 py: Python<'a>,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
444 state: &'a PySharedState,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
445 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
446
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
447 impl<'a> BorrowPyShared<'a> {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
448 fn new(py: Python<'a>, state: &'a PySharedState) -> BorrowPyShared<'a> {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
449 state.increase_borrow_count(py);
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
450 BorrowPyShared { py, state }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
451 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
452 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
453
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
454 impl<'a> Drop for BorrowPyShared<'a> {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
455 fn drop(&mut self) {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
456 self.state.decrease_borrow_count(self.py);
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
457 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
458 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
459
52635
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52634
diff changeset
460 /// An immutable reference to [`PyShareable`] value, not bound to lifetime.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
461 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
462 /// The reference will be invalidated once the original value is mutably
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
463 /// borrowed.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
464 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
465 /// # Safety
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
466 ///
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
467 /// Even though [`SharedByPyObject`] tries to enforce the real lifetime of the
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
468 /// underlying object, the object having the artificial `'static` lifetime
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
469 /// may be exposed to your Rust code. You must be careful to not make a bare
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
470 /// reference outlive the actual object lifetime.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
471 ///
52640
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
472 /// See [`Self::try_borrow_mut()`] for an example of the kind of trouble that
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
473 /// can arise.
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
474 pub struct SharedByPyObject<T: ?Sized> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
475 owner: PyObject,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
476 state: &'static PySharedState,
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
477 /// Generation counter of data `T` captured when SharedByPyObject is
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
478 /// created.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
479 generation: usize,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
480 /// Underlying data of artificial lifetime, which is valid only when
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
481 /// state.generation == self.generation.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
482 data: T,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
483 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
484
52856
189491cea922 pyo3-sharedref: add static assertions that we never implement Deref*
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52640
diff changeset
485 // DO NOT implement Deref or DerefMut for SharedByPyObject<T>! Dereferencing
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
486 // SharedByPyObject without taking Python GIL wouldn't be safe. Also, the
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
487 // underling reference is invalid if generation != state.generation.
52856
189491cea922 pyo3-sharedref: add static assertions that we never implement Deref*
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52640
diff changeset
488 static_assertions_next::assert_impl!(
189491cea922 pyo3-sharedref: add static assertions that we never implement Deref*
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52640
diff changeset
489 for(T) SharedByPyObject<T>: !Deref
189491cea922 pyo3-sharedref: add static assertions that we never implement Deref*
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52640
diff changeset
490 );
189491cea922 pyo3-sharedref: add static assertions that we never implement Deref*
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52640
diff changeset
491
189491cea922 pyo3-sharedref: add static assertions that we never implement Deref*
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52640
diff changeset
492 static_assertions_next::assert_impl!(
189491cea922 pyo3-sharedref: add static assertions that we never implement Deref*
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52640
diff changeset
493 for(T) SharedByPyObject<T>: !DerefMut
189491cea922 pyo3-sharedref: add static assertions that we never implement Deref*
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52640
diff changeset
494 );
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
495
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
496 impl<T: ?Sized> SharedByPyObject<T> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
497 // No panicking version of borrow() and borrow_mut() are implemented
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
498 // because the underlying value is supposed to be mutated in Python
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
499 // world, and the Rust library designer can't prevent it.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
500
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
501 /// Immutably borrows the wrapped value.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
502 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
503 /// Borrowing fails if the underlying reference has been invalidated.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
504 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
505 /// # Safety
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
506 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
507 /// The lifetime of the innermost object is artificial. Do not obtain and
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
508 /// copy it out of the borrow scope.
52640
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
509 ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
510 /// The lifetime of the innermost object is artificial. Do not obtain and
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
511 /// copy it out of the borrow scope. More generally, the returned `&T`
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
512 /// may have a method returning an inner reference, which would typically
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
513 /// be `'static` and not safe without the `owner` Python object, so the
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
514 /// problem might be less obvious than in the example below.
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
515 ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
516 /// The following example does compile and illustrates the problem.
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
517 /// In this case, the data is a `Vec<String>` and the leaked reference
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
518 /// `&'static str`, which points to some element of the vector. This
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
519 /// illustrates that the leaks are not necessarily to the whole of the
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
520 /// shared data.
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
521 ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
522 /// ```no_run
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
523 /// # use pyo3::prelude::*;
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
524 /// # use pyo3_sharedref::PyShareable;
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
525 /// #[pyclass]
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
526 /// struct Owner {
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
527 /// value: PyShareable<Vec<String>>
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
528 /// }
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
529 ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
530 /// #[pymethods]
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
531 /// impl Owner {
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
532 /// #[new]
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
533 /// fn new(s: &str) -> Self {
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
534 /// let split: Vec<_> = s.split(' ').map(String::from).collect();
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
535 /// Self { value: split.into() }
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
536 /// }
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
537 /// }
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
538 ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
539 /// const EMPTY: &'static str = "";
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
540 ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
541 /// let mut outer = EMPTY;
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
542 /// Python::with_gil(|py| {
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
543 /// let owner = Bound::new(py, Owner::new("hello")).unwrap();
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
544 /// let shareable = &owner.borrow().value;
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
545 /// let shared = unsafe { shareable.share(&owner) };
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
546 /// {
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
547 /// let inner = unsafe { shared.try_borrow(py) }.unwrap();
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
548 /// outer = &inner[0]; // Bad, &'static str does outlive the scope
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
549 /// }
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
550 /// });
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
551 /// ```
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
552 pub unsafe fn try_borrow<'a>(
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
553 &'a self,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
554 py: Python<'a>,
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
555 ) -> PyResult<SharedByPyObjectRef<'a, T>> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
556 self.validate_generation(py)?;
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
557 Ok(SharedByPyObjectRef {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
558 _borrow: BorrowPyShared::new(py, self.state),
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
559 data: &self.data,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
560 })
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
561 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
562
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
563 /// Mutably borrows the wrapped value.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
564 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
565 /// Borrowing fails if the underlying reference has been invalidated.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
566 ///
52640
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
567 /// Typically `T` would be an iterator obtained by the [`Self::map`]
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
568 /// method.
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
569 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
570 /// # Safety
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
571 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
572 /// The lifetime of the innermost object is artificial. Do not obtain and
52640
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
573 /// copy it out of the borrow scope. More generally, the returned `&T`
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
574 /// may have a method returning an inner reference, which would typically
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
575 /// be `'static` and not safe without the `owner` Python object, so the
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
576 /// problem might be less obvious than in the example below.
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
577 ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
578 /// The following example does compile and illustrates the problem.
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
579 /// It is very close to the example given in [`Self::try_borrow`] because
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
580 /// the problem does not arise from the mutability of the reference
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
581 /// returned by this function.
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
582 ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
583 /// In this case, the data is a `Vec<String>` and the leaked reference
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
584 /// `&'static str`, which points to some element of the vector. This
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
585 /// illustrates that the leaks are not necessarily to the whole of the
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
586 /// shared data.
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
587 ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
588 /// ```no_run
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
589 /// # use pyo3::prelude::*;
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
590 /// # use pyo3_sharedref::PyShareable;
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
591 /// #[pyclass]
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
592 /// struct Owner {
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
593 /// value: PyShareable<Vec<String>>
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
594 /// }
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
595 ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
596 /// #[pymethods]
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
597 /// impl Owner {
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
598 /// #[new]
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
599 /// fn new(s: &str) -> Self {
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
600 /// let split: Vec<_> = s.split(' ').map(String::from).collect();
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
601 /// Self { value: split.into() }
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
602 /// }
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
603 /// }
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
604 ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
605 /// const EMPTY: &'static str = "";
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
606 ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
607 /// let mut outer = EMPTY;
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
608 /// Python::with_gil(|py| {
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
609 /// let owner = Bound::new(py, Owner::new("hello")).unwrap();
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
610 /// let shareable = &owner.borrow().value;
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
611 /// let shared = unsafe { shareable.share(&owner) };
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
612 /// let mut shared_iter = unsafe { shared.map(py, |o| o.iter()) };
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
613 /// {
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
614 /// let mut iter = unsafe {
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
615 /// shared_iter.try_borrow_mut(py)
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
616 /// }.unwrap();
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
617 /// let inner = iter.next().unwrap(); // Good, in borrow scope
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
618 /// outer = inner; // Bad, &'static str does outlive the scope
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
619 /// }
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
620 /// });
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52639
diff changeset
621 /// ```
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
622 pub unsafe fn try_borrow_mut<'a>(
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
623 &'a mut self,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
624 py: Python<'a>,
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
625 ) -> PyResult<SharedByPyObjectRefMut<'a, T>> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
626 self.validate_generation(py)?;
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
627 Ok(SharedByPyObjectRefMut {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
628 _borrow: BorrowPyShared::new(py, self.state),
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
629 data: &mut self.data,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
630 })
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
631 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
632
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
633 fn validate_generation(&self, py: Python) -> PyResult<()> {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
634 if self.state.current_generation(py) == self.generation {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
635 Ok(())
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
636 } else {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
637 Err(PyRuntimeError::new_err(
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
638 "Cannot access to shared reference after mutation",
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
639 ))
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
640 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
641 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
642 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
643
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
644 impl<T> SharedByPyObject<T> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
645 /// Converts the inner value by the given function.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
646 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
647 /// Typically `T` is a static reference to a collection, and `U` is an
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
648 /// iterator of that collection.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
649 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
650 /// # Panics
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
651 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
652 /// Panics if the underlying reference has been invalidated.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
653 ///
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
654 /// This is typically called immediately after the `SharedByPyObject` is
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
655 /// obtained. At this time, the reference must be valid and no panic
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
656 /// would occur.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
657 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
658 /// # Safety
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
659 ///
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
660 /// The lifetime of the object passed in to the function `f` is artificial.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
661 /// It's typically a static reference, but is valid only while the
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
662 /// corresponding `SharedByPyObject` is alive. Do not copy it out of the
52639
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
663 /// function call. For example, the following does compile:
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
664 ///
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
665 /// ```no_run
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
666 /// # use pyo3::prelude::*;
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
667 /// # use pyo3_sharedref::PyShareable;
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
668 /// #[pyclass]
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
669 /// struct Owner {
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
670 /// value: PyShareable<String>
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
671 /// }
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
672 ///
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
673 /// #[pymethods]
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
674 /// impl Owner {
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
675 /// #[new]
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
676 /// fn new(s: &str) -> Self {
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
677 /// Self { value: s.to_owned().into() }
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
678 /// }
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
679 /// }
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
680 ///
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
681 /// const EMPTY: &'static str = "";
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
682 ///
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
683 /// let mut outer = EMPTY;
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
684 /// Python::with_gil(|py| {
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
685 /// let owner = Bound::new(py, Owner::new("hello")).unwrap();
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
686 /// let shareable = &owner.borrow().value;
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
687 /// let shared = unsafe { shareable.share(&owner) };
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
688 ///
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
689 /// unsafe { shared.map(py, |o| { outer = o }) }; // Bad
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
690 /// });
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52637
diff changeset
691 /// ```
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
692 pub unsafe fn map<U>(
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
693 self,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
694 py: Python,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
695 f: impl FnOnce(T) -> U,
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
696 ) -> SharedByPyObject<U> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
697 // Needs to test the generation value to make sure self.data reference
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
698 // is still intact.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
699 self.validate_generation(py)
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
700 .expect("map() over invalidated shared reference");
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
701
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
702 // f() could make the self.data outlive. That's why map() is unsafe.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
703 // In order to make this function safe, maybe we'll need a way to
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
704 // temporarily restrict the lifetime of self.data and translate the
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
705 // returned object back to Something<'static>.
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
706 let new_data = f(self.data);
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
707 SharedByPyObject {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
708 owner: self.owner,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
709 state: self.state,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
710 generation: self.generation,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
711 data: new_data,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
712 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
713 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
714 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
715
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
716 /// An immutably borrowed reference to a shared value.
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
717 pub struct SharedByPyObjectRef<'a, T: 'a + ?Sized> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
718 _borrow: BorrowPyShared<'a>,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
719 data: &'a T,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
720 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
721
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
722 impl<'a, T: ?Sized> Deref for SharedByPyObjectRef<'a, T> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
723 type Target = T;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
724
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
725 fn deref(&self) -> &T {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
726 self.data
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
727 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
728 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
729
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
730 /// A mutably borrowed reference to a shared value.
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
731 pub struct SharedByPyObjectRefMut<'a, T: 'a + ?Sized> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
732 _borrow: BorrowPyShared<'a>,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
733 data: &'a mut T,
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
734 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
735
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
736 impl<'a, T: ?Sized> Deref for SharedByPyObjectRefMut<'a, T> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
737 type Target = T;
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
738
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
739 fn deref(&self) -> &T {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
740 self.data
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
741 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
742 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
743
52636
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52635
diff changeset
744 impl<'a, T: ?Sized> DerefMut for SharedByPyObjectRefMut<'a, T> {
52631
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
745 fn deref_mut(&mut self) -> &mut T {
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
746 self.data
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
747 }
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
748 }
52872
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
749
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
750 /// Defines a Python iterator over a Rust iterator.
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
751 ///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
752 /// TODO: this is a bit awkward to use, and a better (more complicated)
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
753 /// procedural macro would simplify the interface a lot.
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
754 ///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
755 /// # Parameters
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
756 ///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
757 /// * `$name` is the identifier to give to the resulting Rust struct.
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
758 /// * `$success_type` is the resulting Python object. It can be a bultin type,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
759 /// (e.g., `PyBytes`), or any `PyClass`.
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
760 /// * `$owner_type` is the type owning the data
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
761 /// * `$owner_attr` is the name of the shareable attribute in `$owner_type`
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
762 /// * `$shared_type` is the type wrapped in `SharedByPyObject`, typically
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
763 /// `SomeIter<'static>`
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
764 /// * `$iter_func` is a function to obtain the Rust iterator from the content
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
765 /// of the shareable attribute. It can be a closure.
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
766 /// * `$result_func` is a function for converting items returned by the Rust
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
767 /// iterator into `PyResult<Option<Py<$success_type>`.
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
768 ///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
769 /// # Safety
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
770 ///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
771 /// `$success_func` may take a reference, whose lifetime may be articial.
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
772 /// Do not copy it out of the function call (this would be possible only
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
773 /// with inner mutability).
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
774 ///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
775 /// # Example
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
776 ///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
777 /// The iterator example in [`PyShareable`] can be rewritten as
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
778 ///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
779 /// ```
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
780 /// use pyo3::prelude::*;
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
781 /// use pyo3_sharedref::*;
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
782 ///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
783 /// use pyo3::types::{PyTuple, PyInt};
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
784 /// use std::collections::{hash_set::Iter as IterHashSet, HashSet};
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
785 /// use std::vec::Vec;
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
786 ///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
787 /// #[pyclass(sequence)]
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
788 /// struct Set {
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
789 /// rust_set: PyShareable<HashSet<i32>>,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
790 /// }
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
791 ///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
792 /// #[pymethods]
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
793 /// impl Set {
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
794 /// #[new]
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
795 /// fn new(values: &Bound<'_, PyTuple>) -> PyResult<Self> {
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
796 /// let as_vec = values.extract::<Vec<i32>>()?;
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
797 /// let s: HashSet<_> = as_vec.iter().copied().collect();
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
798 /// Ok(Self { rust_set: s.into() })
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
799 /// }
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
800 ///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
801 /// fn __iter__(slf: &Bound<'_, Self>) -> PyResult<SetIterator> {
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
802 /// SetIterator::new(slf)
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
803 /// }
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
804 /// }
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
805 ///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
806 /// py_shared_iterator!(
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
807 /// SetIterator,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
808 /// PyInt,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
809 /// Set,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
810 /// rust_set,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
811 /// IterHashSet<'static, i32>,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
812 /// |hash_set| hash_set.iter(),
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
813 /// it_next_result
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
814 /// );
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
815 ///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
816 /// fn it_next_result(py: Python, res: &i32) -> PyResult<Option<Py<PyInt>>> {
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
817 /// Ok(Some((*res).into_pyobject(py)?.unbind()))
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
818 /// }
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
819 /// ```
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
820 ///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
821 /// In the example above, `$result_func` is fairly trivial, and can be replaced
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
822 /// by a closure, but things can get more complicated if the Rust
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
823 /// iterator itself returns `Result<T, E>` with `T` not implementing
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
824 /// `IntoPyObject` and `E` needing to be converted.
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
825 /// Also the closure variant is fairly obscure:
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
826 ///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
827 /// ```ignore
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
828 /// py_shared_iterator!(
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
829 /// SetIterator,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
830 /// PyInt,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
831 /// Set,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
832 /// rust_set,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
833 /// IterHashSet<'static, i32>,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
834 /// |hash_set| hash_set.iter(),
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
835 /// (|py, i: &i32| Ok(Some((*i).into_pyobject(py)?.unbind())))
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
836 /// )
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
837 /// ```
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
838 #[macro_export]
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
839 macro_rules! py_shared_iterator {
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
840 (
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
841 $name: ident,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
842 $success_type: ty,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
843 $owner_type: ident,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
844 $owner_attr: ident,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
845 $shared_type: ty,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
846 $iter_func: expr,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
847 $result_func: expr
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
848 ) => {
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
849 #[pyclass]
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
850 pub struct $name {
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
851 inner: pyo3_sharedref::SharedByPyObject<$shared_type>,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
852 }
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
853
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
854 #[pymethods]
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
855 impl $name {
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
856 #[new]
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
857 fn new(owner: &Bound<'_, $owner_type>) -> PyResult<Self> {
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
858 let inner = &owner.borrow().$owner_attr;
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
859 // Safety: the data is indeed owned by `owner`
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
860 let shared_iter =
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
861 unsafe { inner.share_map(owner, $iter_func) };
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
862 Ok(Self { inner: shared_iter })
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
863 }
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
864
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
865 fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> {
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
866 slf
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
867 }
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
868
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
869 fn __next__(
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
870 mut slf: PyRefMut<'_, Self>,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
871 ) -> PyResult<Option<Py<$success_type>>> {
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
872 let py = slf.py();
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
873 let shared = &mut slf.inner;
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
874 // Safety: we do not leak references derived from the internal
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
875 // 'static reference.
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
876 let mut inner = unsafe { shared.try_borrow_mut(py) }?;
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
877 match inner.next() {
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
878 None => Ok(None),
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
879 Some(res) => $result_func(py, res),
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
880 }
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
881 }
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
882 }
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
883 };
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52856
diff changeset
884 }