|
1 | 1 | #![cfg(feature = "uuid")] |
2 | 2 |
|
3 | | -//! Conversions to and from [uuid](https://docs.rs/uuid/latest/uuid/)'s [`Uuid`] type. |
| 3 | +//! Conversions to and from [uuid](https://docs.rs/uuid/latest/uuid/)'s [`Uuid`] and [`NonNilUuid`] types. |
4 | 4 | //! |
5 | 5 | //! This is useful for converting Python's uuid.UUID into and from a native Rust type. |
6 | 6 | //! |
|
63 | 63 | //! returned_uuid = get_uuid(py_uuid) |
64 | 64 | //! assert py_uuid == returned_uuid |
65 | 65 | //! ``` |
66 | | -use uuid::Uuid; |
| 66 | +use uuid::{NonNilUuid, Uuid}; |
67 | 67 |
|
68 | 68 | use crate::conversion::IntoPyObject; |
69 | | -use crate::exceptions::PyTypeError; |
| 69 | +use crate::exceptions::{PyTypeError, PyValueError}; |
70 | 70 | use crate::instance::Bound; |
71 | 71 | use crate::sync::PyOnceLock; |
72 | 72 | use crate::types::any::PyAnyMethods; |
@@ -116,6 +116,35 @@ impl<'py> IntoPyObject<'py> for &Uuid { |
116 | 116 | } |
117 | 117 | } |
118 | 118 |
|
| 119 | +impl FromPyObject<'_, '_> for NonNilUuid { |
| 120 | + type Error = PyErr; |
| 121 | + |
| 122 | + fn extract(obj: Borrowed<'_, '_, PyAny>) -> PyResult<Self> { |
| 123 | + let uuid: Uuid = obj.extract()?; |
| 124 | + NonNilUuid::new(uuid).ok_or_else(|| PyValueError::new_err("UUID is nil")) |
| 125 | + } |
| 126 | +} |
| 127 | + |
| 128 | +impl<'py> IntoPyObject<'py> for NonNilUuid { |
| 129 | + type Target = PyAny; |
| 130 | + type Output = Bound<'py, Self::Target>; |
| 131 | + type Error = PyErr; |
| 132 | + |
| 133 | + fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> { |
| 134 | + Uuid::from(self).into_pyobject(py) |
| 135 | + } |
| 136 | +} |
| 137 | + |
| 138 | +impl<'py> IntoPyObject<'py> for &NonNilUuid { |
| 139 | + type Target = PyAny; |
| 140 | + type Output = Bound<'py, Self::Target>; |
| 141 | + type Error = PyErr; |
| 142 | + |
| 143 | + fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> { |
| 144 | + (*self).into_pyobject(py) |
| 145 | + } |
| 146 | +} |
| 147 | + |
119 | 148 | #[cfg(test)] |
120 | 149 | mod tests { |
121 | 150 | use super::*; |
@@ -183,4 +212,19 @@ mod tests { |
183 | 212 | Uuid::parse_str("a6cc5730-2261-11ee-9c43-2eb5a363657c").unwrap(), |
184 | 213 | "a6cc5730-2261-11ee-9c43-2eb5a363657c" |
185 | 214 | ); |
| 215 | + |
| 216 | + #[test] |
| 217 | + fn test_non_nil_uuid() { |
| 218 | + Python::attach(|py| { |
| 219 | + let rs_uuid = NonNilUuid::new(Uuid::max()).unwrap(); |
| 220 | + let py_uuid = rs_uuid.into_pyobject(py).unwrap(); |
| 221 | + |
| 222 | + let extract_uuid: NonNilUuid = py_uuid.extract().unwrap(); |
| 223 | + assert_eq!(extract_uuid, rs_uuid); |
| 224 | + |
| 225 | + let nil_uuid = Uuid::nil().into_pyobject(py).unwrap(); |
| 226 | + let extract_nil: PyResult<NonNilUuid> = nil_uuid.extract(); |
| 227 | + assert!(extract_nil.is_err()); |
| 228 | + }) |
| 229 | + } |
186 | 230 | } |
0 commit comments