rust/pyo3-sharedref/src/lib.rs
author Pierre-Yves David <pierre-yves.david@octobus.net>
Tue, 11 Mar 2025 02:29:42 +0100
branchstable
changeset 53042 cdd7bf612c7b
parent 52860 8f6d25439bdc
permissions -rw-r--r--
bundle-spec: properly format boolean parameter (issue6960) This was breaking automatic clone bundle generation. This changeset fixes it and add a test to catch it in the future.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
52606
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
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
    42
/// [`SharedByPyObject`] fields.
52606
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.
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
    50
/// The [`PyShareableRef::share_immutable()`] and
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
    51
/// [`SharedByPyObject::map()`] methods provide a way around this issue.
52606
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    52
///
52610
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52609
diff changeset
    53
/// [`PyShareable`] is [`Sync`]. It works internally with locks and
52606
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
///
52610
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52609
diff changeset
    56
/// [`PyShareable`] is merely a data struct to be stored in its
52606
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    57
/// owner Python object.
52610
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52609
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: 52609
diff changeset
    59
/// is a lifetime-bound reference to the [`PyShareable`].
52606
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 {
52610
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52609
diff changeset
    77
///     rust_set: PyShareable<HashSet<i32>>,
52606
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();
52608
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52606
diff changeset
    86
///         Ok(Self { rust_set: s.into() })
52606
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;
52608
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52606
diff changeset
    95
///         let shared_ref = unsafe { rust_set.borrow_with_owner(slf) };
52609
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52608
diff changeset
    96
///         let mut set_ref = shared_ref.write();
52606
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 {
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   104
///     rust_iter: SharedByPyObject<IterHashSet<'static, i32>>,
52606
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;
52612
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   113
///         let iter = unsafe { rust_set.share_map(s, |o| o.iter()) };
52606
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();
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   125
///         let shared = &mut slf.rust_iter;
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   126
///         let mut inner = unsafe { shared.try_borrow_mut(py) }?;
52606
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,
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   159
///         "RuntimeError('Cannot access to shared reference after mutation')"
52606
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.
52610
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52609
diff changeset
   168
///
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52609
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: 52609
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: 52609
diff changeset
   171
/// a lifetime-bound reference to the [`PyShareable`].
52606
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   172
#[derive(Debug)]
52610
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52609
diff changeset
   173
pub struct PyShareable<T: ?Sized> {
52606
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
52612
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   178
impl<T: 'static> PyShareable<T> {
52606
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
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
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: 52610
diff changeset
   186
    /// reference.
52608
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52606
diff changeset
   187
    pub unsafe fn borrow_with_owner<'py>(
52606
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>,
52610
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52609
diff changeset
   190
    ) -> PyShareableRef<'py, T> {
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52609
diff changeset
   191
        PyShareableRef {
52606
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
    }
52612
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   197
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   198
    /// Share for other Python objects
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   199
    ///
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   200
    /// # Safety
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   201
    ///
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
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: 52611
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: 52611
diff changeset
   204
    pub unsafe fn share<'py>(
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   205
        &'py self,
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   206
        owner: &'py Bound<'py, PyAny>,
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   207
    ) -> SharedByPyObject<&'static T> {
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
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: 52611
diff changeset
   209
    }
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   210
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
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: 52611
diff changeset
   212
    /// with a closure
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   213
    ///
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   214
    /// # Safety
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   215
    ///
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
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: 52611
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: 52611
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: 52611
diff changeset
   219
        &'py self,
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   220
        owner: &'py Bound<'py, PyAny>,
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
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: 52611
diff changeset
   222
    ) -> SharedByPyObject<U> {
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
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: 52611
diff changeset
   224
    }
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   225
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   226
    /// # Safety
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   227
    ///
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
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: 52611
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: 52611
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: 52611
diff changeset
   231
        &'py self,
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   232
        owner: &'py Bound<'py, PyAny>,
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   233
    ) -> Result<SharedByPyObject<&'static T>, TryShareError> {
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
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: 52611
diff changeset
   235
    }
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   236
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   237
    /// # Safety
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   238
    ///
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
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: 52611
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: 52611
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: 52611
diff changeset
   242
        &'py self,
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
diff changeset
   243
        owner: &'py Bound<'py, PyAny>,
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
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: 52611
diff changeset
   245
    ) -> Result<SharedByPyObject<U>, TryShareError> {
a945845137b1 rust-pyo3-sharedref: share/map methods on PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52611
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: 52611
diff changeset
   247
    }
52606
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
52610
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52609
diff changeset
   250
impl<T> From<T> for PyShareable<T> {
52608
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52606
diff changeset
   251
    fn from(value: T) -> Self {
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52606
diff changeset
   252
        Self {
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52606
diff changeset
   253
            state: PySharedState::new(),
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52606
diff changeset
   254
            data: value.into(),
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52606
diff changeset
   255
        }
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52606
diff changeset
   256
    }
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52606
diff changeset
   257
}
d85514a88706 rust-pyo3-sharedref: reworked constructors
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52606
diff changeset
   258
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   259
/// Errors that can happen in `share_immutable()`
52606
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   260
#[derive(Debug, PartialEq, Eq)]
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   261
pub enum TryShareError {
52606
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
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   268
impl<T> From<TryLockError<T>> for TryShareError {
52606
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
52610
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52609
diff changeset
   277
/// A reference to [`PyShareable`] and its legit owner Python object.
52606
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   278
///
52610
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52609
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: 52609
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: 52609
diff changeset
   281
/// we make one.
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52609
diff changeset
   282
pub struct PyShareableRef<'py, T: 'py + ?Sized> {
52606
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
52610
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52609
diff changeset
   288
impl<'py, T: ?Sized> PyShareableRef<'py, T> {
52609
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52608
diff changeset
   289
    /// Take the lock on the wrapped value for read-only operations.
52606
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
    ///
52609
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52608
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: 52608
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: 52608
diff changeset
   295
        self.try_read().expect("already mutably borrowed")
52606
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.
52609
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52608
diff changeset
   300
    pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<'py, T>> {
52606
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   301
        // state isn't involved since
52609
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52608
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: 52608
diff changeset
   303
        // - and data.try_write() would fail while self is borrowed.
52606
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
52609
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52608
diff changeset
   307
    /// Take the lock on the wrapped value for write operations.
52606
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   308
    ///
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   309
    /// Any existing shared references will be invalidated.
52606
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
    ///
52609
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52608
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: 52608
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: 52608
diff changeset
   315
        self.try_write().expect("already borrowed")
52606
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.
52609
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52608
diff changeset
   320
    pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<'py, T>> {
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   321
        // the value may be immutably borrowed through SharedByPyObject
52606
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 {
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   323
            // propagate borrow-by-shared state to data to get BorrowMutError
52606
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.
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
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: 52610
diff changeset
   340
        self.try_share_immutable()
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   341
            .expect("already mutably borrowed")
52606
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.
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   346
    pub fn try_share_immutable(
52606
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   347
        &self,
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   348
    ) -> Result<SharedByPyObject<&'static T>, TryShareError> {
52606
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.
52609
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52608
diff changeset
   351
        let data_ref = self.try_read()?;
52606
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,
52609
d1e304025b90 rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52608
diff changeset
   354
        // but the data pointer can be invalidated by write().
52606
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;
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   358
        Ok(SharedByPyObject::<&'static T> {
52606
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
///
52610
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52609
diff changeset
   377
/// `PySharedState` is owned by `PyShareable`, and is shared across its
52606
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
52610
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52609
diff changeset
   382
///   [`PyShareable`] is allowed only through its `write()`.
52606
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.
52610
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52609
diff changeset
   385
/// - The underlying `RefCell`, which prevents `PyShareable` value from being
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   386
///   directly borrowed or shared while it is mutably borrowed.
52606
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
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
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: 52610
diff changeset
   389
///   `SharedByPyObject` is borrowed.
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
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: 52610
diff changeset
   391
///   `SharedByPyObject`
52606
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.
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   399
    /// The number of immutable references borrowed through shared reference.
52606
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
52610
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52609
diff changeset
   441
/// immutably borrowed without using the `RwLock` interface.
52606
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
52610
c25d345f5aa5 rust-pyo3-sharedref: renamed PySharedRefCell to PyShareable
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52609
diff changeset
   460
/// An immutable reference to [`PyShareable`] value, not bound to lifetime.
52606
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
///
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   467
/// Even though [`SharedByPyObject`] tries to enforce the real lifetime of the
52606
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
///
52615
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
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: 52614
diff changeset
   473
/// can arise.
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   474
pub struct SharedByPyObject<T: ?Sized> {
52606
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,
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   477
    /// Generation counter of data `T` captured when SharedByPyObject is
52606
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
52843
189491cea922 pyo3-sharedref: add static assertions that we never implement Deref*
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52615
diff changeset
   485
// DO NOT implement Deref or DerefMut for SharedByPyObject<T>! Dereferencing
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
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: 52610
diff changeset
   487
// underling reference is invalid if generation != state.generation.
52843
189491cea922 pyo3-sharedref: add static assertions that we never implement Deref*
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52615
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: 52615
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: 52615
diff changeset
   490
);
189491cea922 pyo3-sharedref: add static assertions that we never implement Deref*
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52615
diff changeset
   491
189491cea922 pyo3-sharedref: add static assertions that we never implement Deref*
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52615
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: 52615
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: 52615
diff changeset
   494
);
52606
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   495
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   496
impl<T: ?Sized> SharedByPyObject<T> {
52606
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.
52615
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   509
    ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
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: 52614
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: 52614
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: 52614
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: 52614
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: 52614
diff changeset
   515
    ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
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: 52614
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: 52614
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: 52614
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: 52614
diff changeset
   520
    /// shared data.
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   521
    ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   522
    /// ```no_run
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   523
    /// # use pyo3::prelude::*;
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   524
    /// # use pyo3_sharedref::PyShareable;
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   525
    /// #[pyclass]
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   526
    /// struct Owner {
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   527
    ///     value: PyShareable<Vec<String>>
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   528
    /// }
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   529
    ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   530
    /// #[pymethods]
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   531
    /// impl Owner {
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   532
    ///     #[new]
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   533
    ///     fn new(s: &str) -> Self {
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
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: 52614
diff changeset
   535
    ///         Self { value: split.into() }
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   536
    ///     }
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   537
    /// }
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   538
    ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   539
    /// const EMPTY: &'static str = "";
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   540
    ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   541
    /// let mut outer = EMPTY;
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   542
    /// Python::with_gil(|py| {
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
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: 52614
diff changeset
   544
    ///     let shareable = &owner.borrow().value;
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   545
    ///     let shared = unsafe { shareable.share(&owner) };
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   546
    ///     {
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
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: 52614
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: 52614
diff changeset
   549
    ///     }
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   550
    /// });
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   551
    /// ```
52606
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>,
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   555
    ) -> PyResult<SharedByPyObjectRef<'a, T>> {
52606
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   556
        self.validate_generation(py)?;
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   557
        Ok(SharedByPyObjectRef {
52606
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
    ///
52615
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
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: 52614
diff changeset
   568
    /// method.
52606
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
52615
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
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: 52614
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: 52614
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: 52614
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: 52614
diff changeset
   577
    ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
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: 52614
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: 52614
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: 52614
diff changeset
   581
    /// returned by this function.
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   582
    ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
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: 52614
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: 52614
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: 52614
diff changeset
   586
    /// shared data.
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   587
    ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   588
    /// ```no_run
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   589
    /// # use pyo3::prelude::*;
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   590
    /// # use pyo3_sharedref::PyShareable;
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   591
    /// #[pyclass]
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   592
    /// struct Owner {
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   593
    ///     value: PyShareable<Vec<String>>
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   594
    /// }
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   595
    ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   596
    /// #[pymethods]
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   597
    /// impl Owner {
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   598
    ///     #[new]
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   599
    ///     fn new(s: &str) -> Self {
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
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: 52614
diff changeset
   601
    ///         Self { value: split.into() }
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   602
    ///     }
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   603
    /// }
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   604
    ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   605
    /// const EMPTY: &'static str = "";
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   606
    ///
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   607
    /// let mut outer = EMPTY;
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   608
    /// Python::with_gil(|py| {
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
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: 52614
diff changeset
   610
    ///     let shareable = &owner.borrow().value;
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   611
    ///     let shared = unsafe { shareable.share(&owner) };
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
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: 52614
diff changeset
   613
    ///     {
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   614
    ///         let mut iter = unsafe {
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   615
    ///             shared_iter.try_borrow_mut(py)
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   616
    ///         }.unwrap();
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
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: 52614
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: 52614
diff changeset
   619
    ///     }
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   620
    /// });
78b2894cd58c rust-pyo3-sharedref: demonstrate SharedByPyObject borrow unsafety
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52614
diff changeset
   621
    /// ```
52606
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>,
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   625
    ) -> PyResult<SharedByPyObjectRefMut<'a, T>> {
52606
be765f6797cc rust-pyo3: initial port of PySharedRef
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
   626
        self.validate_generation(py)?;
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   627
        Ok(SharedByPyObjectRefMut {
52606
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(
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   638
                "Cannot access to shared reference after mutation",
52606
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
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   644
impl<T> SharedByPyObject<T> {
52606
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
    ///
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   654
    /// This is typically called immediately after the `SharedByPyObject` is
52606
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
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   662
    /// corresponding `SharedByPyObject` is alive. Do not copy it out of the
52614
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
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: 52612
diff changeset
   664
    ///
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
diff changeset
   665
    /// ```no_run
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
diff changeset
   666
    /// # use pyo3::prelude::*;
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
diff changeset
   667
    /// # use pyo3_sharedref::PyShareable;
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
diff changeset
   668
    /// #[pyclass]
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
diff changeset
   669
    /// struct Owner {
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
diff changeset
   670
    ///     value: PyShareable<String>
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
diff changeset
   671
    /// }
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
diff changeset
   672
    ///
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
diff changeset
   673
    /// #[pymethods]
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
diff changeset
   674
    /// impl Owner {
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
diff changeset
   675
    ///     #[new]
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
diff changeset
   676
    ///     fn new(s: &str) -> Self {
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
diff changeset
   677
    ///         Self { value: s.to_owned().into() }
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
diff changeset
   678
    ///     }
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
diff changeset
   679
    /// }
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
diff changeset
   680
    ///
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
diff changeset
   681
    /// const EMPTY: &'static str = "";
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
diff changeset
   682
    ///
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
diff changeset
   683
    /// let mut outer = EMPTY;
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
diff changeset
   684
    /// Python::with_gil(|py| {
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
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: 52612
diff changeset
   686
    ///     let shareable = &owner.borrow().value;
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
diff changeset
   687
    ///     let shared = unsafe { shareable.share(&owner) };
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
diff changeset
   688
    ///
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
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: 52612
diff changeset
   690
    /// });
76a0bdb0e4ca rust-pyo3-sharedref: demonstrating unsafety of map()
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52612
diff changeset
   691
    /// ```
52606
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,
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   696
    ) -> SharedByPyObject<U> {
52606
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)
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   700
            .expect("map() over invalidated shared reference");
52606
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);
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   707
        SharedByPyObject {
52606
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
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
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: 52610
diff changeset
   717
pub struct SharedByPyObjectRef<'a, T: 'a + ?Sized> {
52606
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
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   722
impl<'a, T: ?Sized> Deref for SharedByPyObjectRef<'a, T> {
52606
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
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
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: 52610
diff changeset
   731
pub struct SharedByPyObjectRefMut<'a, T: 'a + ?Sized> {
52606
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
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   736
impl<'a, T: ?Sized> Deref for SharedByPyObjectRefMut<'a, T> {
52606
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
52611
4a73eb3923ac rust-pyo3-sharedref: renamed UnsafePyLeaked to SharedByPyObject
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52610
diff changeset
   744
impl<'a, T: ?Sized> DerefMut for SharedByPyObjectRefMut<'a, T> {
52606
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
}
52860
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   749
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
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: 52843
diff changeset
   751
///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
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: 52843
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: 52843
diff changeset
   754
///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   755
/// # Parameters
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   756
///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
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: 52843
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: 52843
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: 52843
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: 52843
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: 52843
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: 52843
diff changeset
   763
///   `SomeIter<'static>`
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
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: 52843
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: 52843
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: 52843
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: 52843
diff changeset
   768
///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   769
/// # Safety
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   770
///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
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: 52843
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: 52843
diff changeset
   773
/// with inner mutability).
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   774
///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   775
/// # Example
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   776
///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
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: 52843
diff changeset
   778
///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   779
/// ```
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   780
/// use pyo3::prelude::*;
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   781
/// use pyo3_sharedref::*;
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   782
///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   783
/// use pyo3::types::{PyTuple, PyInt};
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
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: 52843
diff changeset
   785
/// use std::vec::Vec;
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   786
///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   787
/// #[pyclass(sequence)]
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   788
/// struct Set {
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   789
///     rust_set: PyShareable<HashSet<i32>>,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   790
/// }
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   791
///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   792
/// #[pymethods]
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   793
/// impl Set {
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   794
///     #[new]
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
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: 52843
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: 52843
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: 52843
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: 52843
diff changeset
   799
///     }
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   800
///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
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: 52843
diff changeset
   802
///         SetIterator::new(slf)
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   803
///     }
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   804
/// }
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   805
///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   806
/// py_shared_iterator!(
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   807
///    SetIterator,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   808
///    PyInt,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   809
///    Set,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   810
///    rust_set,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   811
///    IterHashSet<'static, i32>,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   812
///    |hash_set| hash_set.iter(),
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   813
///    it_next_result
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   814
/// );
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   815
///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
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: 52843
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: 52843
diff changeset
   818
/// }
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   819
/// ```
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   820
///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
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: 52843
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: 52843
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: 52843
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: 52843
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: 52843
diff changeset
   826
///
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   827
/// ```ignore
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   828
/// py_shared_iterator!(
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   829
///    SetIterator,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   830
///    PyInt,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   831
///    Set,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   832
///    rust_set,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   833
///    IterHashSet<'static, i32>,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   834
///    |hash_set| hash_set.iter(),
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
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: 52843
diff changeset
   836
/// )
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   837
/// ```
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   838
#[macro_export]
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   839
macro_rules! py_shared_iterator {
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   840
    (
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   841
        $name: ident,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   842
        $success_type: ty,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   843
        $owner_type: ident,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   844
        $owner_attr: ident,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   845
        $shared_type: ty,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   846
        $iter_func: expr,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   847
        $result_func: expr
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   848
    ) => {
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   849
        #[pyclass]
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   850
        pub struct $name {
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
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: 52843
diff changeset
   852
        }
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   853
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   854
        #[pymethods]
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   855
        impl $name {
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   856
            #[new]
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
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: 52843
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: 52843
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: 52843
diff changeset
   860
                let shared_iter =
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
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: 52843
diff changeset
   862
                Ok(Self { inner: shared_iter })
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   863
            }
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   864
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
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: 52843
diff changeset
   866
                slf
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   867
            }
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   868
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   869
            fn __next__(
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   870
                mut slf: PyRefMut<'_, Self>,
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   871
            ) -> PyResult<Option<Py<$success_type>>> {
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   872
                let py = slf.py();
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   873
                let shared = &mut slf.inner;
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
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: 52843
diff changeset
   875
                // 'static reference.
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
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: 52843
diff changeset
   877
                match inner.next() {
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   878
                    None => Ok(None),
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
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: 52843
diff changeset
   880
                }
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   881
            }
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   882
        }
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   883
    };
8f6d25439bdc rust-pyo3-sharedref: macro to define Python iterators
Georges Racinet <georges.racinet@cloudcrane.io>
parents: 52843
diff changeset
   884
}