Skip to content

Commit 6d0976c

Browse files
Add IntoPyObject & FromPyObject for Arc<T>
1 parent fdf62e0 commit 6d0976c

File tree

3 files changed

+87
-0
lines changed

3 files changed

+87
-0
lines changed

newsfragments/4987.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add `IntoPyObject` & `FromPyObject` for `Arc<T>`

src/conversions/std/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ mod path;
99
mod set;
1010
mod slice;
1111
mod string;
12+
mod sync;
1213
mod time;
1314
mod vec;

src/conversions/std/sync.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#[cfg(feature = "experimental-inspect")]
2+
use crate::inspect::types::TypeInfo;
3+
use crate::types::PyAnyMethods;
4+
use crate::{Bound, BoundObject, FromPyObject, IntoPyObject, PyAny, PyErr, PyResult, Python};
5+
use std::sync::Arc;
6+
7+
// TODO find a better way (without the extra type parameters) to name the associated types in the trait.
8+
impl<'py, A, T, O, E> IntoPyObject<'py> for Arc<A>
9+
where
10+
for<'a> &'a A: IntoPyObject<'py, Target = T, Output = O, Error = E>,
11+
O: BoundObject<'py, T>,
12+
E: Into<PyErr>,
13+
{
14+
type Target = T;
15+
type Output = O;
16+
type Error = E;
17+
18+
#[inline]
19+
fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
20+
(&*self).into_pyobject(py)
21+
}
22+
23+
#[cfg(feature = "experimental-inspect")]
24+
fn type_output() -> TypeInfo {
25+
<&A as IntoPyObject<'py>>::type_output()
26+
}
27+
}
28+
29+
impl<'a, 'py, T> IntoPyObject<'py> for &'a Arc<T>
30+
where
31+
&'a T: IntoPyObject<'py>,
32+
{
33+
type Target = <&'a T as IntoPyObject<'py>>::Target;
34+
type Output = <&'a T as IntoPyObject<'py>>::Output;
35+
type Error = <&'a T as IntoPyObject<'py>>::Error;
36+
37+
#[inline]
38+
fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
39+
(&**self).into_pyobject(py)
40+
}
41+
42+
#[cfg(feature = "experimental-inspect")]
43+
fn type_output() -> TypeInfo {
44+
<&'a T as IntoPyObject<'py>>::type_output()
45+
}
46+
}
47+
48+
impl<'py, T> FromPyObject<'py> for Arc<T>
49+
where
50+
T: FromPyObject<'py>,
51+
{
52+
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
53+
ob.extract::<T>().map(Arc::new)
54+
}
55+
56+
#[cfg(feature = "experimental-inspect")]
57+
fn type_input() -> TypeInfo {
58+
T::type_input()
59+
}
60+
}
61+
62+
#[cfg(test)]
63+
mod tests {
64+
use super::*;
65+
use crate::types::PyInt;
66+
use crate::Python;
67+
68+
#[test]
69+
fn test_arc_into_pyobject() {
70+
macro_rules! test_roundtrip {
71+
($arc:expr) => {
72+
Python::with_gil(|py| {
73+
let arc = $arc;
74+
let obj: Bound<'_, PyInt> = arc.into_pyobject(py).unwrap();
75+
assert_eq!(obj.extract::<i32>().unwrap(), 42);
76+
let roundtrip = obj.extract::<Arc<i32>>().unwrap();
77+
assert_eq!(&42, roundtrip.as_ref());
78+
});
79+
};
80+
}
81+
82+
test_roundtrip!(Arc::new(42));
83+
test_roundtrip!(&Arc::new(42));
84+
}
85+
}

0 commit comments

Comments
 (0)