pyo3/conversions/std/
option.rs1use crate::{
2 conversion::IntoPyObject, ffi, types::any::PyAnyMethods, AsPyPointer, Bound, BoundObject,
3 FromPyObject, PyAny, PyObject, PyResult, Python,
4};
5
6#[allow(deprecated)]
9impl<T> crate::ToPyObject for Option<T>
10where
11 T: crate::ToPyObject,
12{
13 fn to_object(&self, py: Python<'_>) -> PyObject {
14 self.as_ref()
15 .map_or_else(|| py.None(), |val| val.to_object(py))
16 }
17}
18
19#[allow(deprecated)]
20impl<T> crate::IntoPy<PyObject> for Option<T>
21where
22 T: crate::IntoPy<PyObject>,
23{
24 fn into_py(self, py: Python<'_>) -> PyObject {
25 self.map_or_else(|| py.None(), |val| val.into_py(py))
26 }
27}
28
29impl<'py, T> IntoPyObject<'py> for Option<T>
30where
31 T: IntoPyObject<'py>,
32{
33 type Target = PyAny;
34 type Output = Bound<'py, Self::Target>;
35 type Error = T::Error;
36
37 fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
38 self.map_or_else(
39 || Ok(py.None().into_bound(py)),
40 |val| {
41 val.into_pyobject(py)
42 .map(BoundObject::into_any)
43 .map(BoundObject::into_bound)
44 },
45 )
46 }
47}
48
49impl<'a, 'py, T> IntoPyObject<'py> for &'a Option<T>
50where
51 &'a T: IntoPyObject<'py>,
52{
53 type Target = PyAny;
54 type Output = Bound<'py, Self::Target>;
55 type Error = <&'a T as IntoPyObject<'py>>::Error;
56
57 #[inline]
58 fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
59 self.as_ref().into_pyobject(py)
60 }
61}
62
63impl<'py, T> FromPyObject<'py> for Option<T>
64where
65 T: FromPyObject<'py>,
66{
67 fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult<Self> {
68 if obj.is_none() {
69 Ok(None)
70 } else {
71 obj.extract().map(Some)
72 }
73 }
74}
75
76unsafe impl<T> AsPyPointer for Option<T>
78where
79 T: AsPyPointer,
80{
81 #[inline]
82 fn as_ptr(&self) -> *mut ffi::PyObject {
83 self.as_ref()
84 .map_or_else(std::ptr::null_mut, |t| t.as_ptr())
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use crate::{PyObject, Python};
91
92 #[test]
93 fn test_option_as_ptr() {
94 Python::with_gil(|py| {
95 use crate::AsPyPointer;
96 let mut option: Option<PyObject> = None;
97 assert_eq!(option.as_ptr(), std::ptr::null_mut());
98
99 let none = py.None();
100 option = Some(none.clone_ref(py));
101
102 let ref_cnt = none.get_refcnt(py);
103 assert_eq!(option.as_ptr(), none.as_ptr());
104
105 assert_eq!(none.get_refcnt(py), ref_cnt);
107 });
108 }
109}