Mercurial > public > mercurial-scm > hg-stable
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 |
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 } |