nautilus_core/python/
uuid.rs1use std::{
19 collections::hash_map::DefaultHasher,
20 hash::{Hash, Hasher},
21 str::FromStr,
22};
23
24use pyo3::{
25 IntoPyObjectExt,
26 prelude::*,
27 pyclass::CompareOp,
28 types::{PyBytes, PyTuple},
29};
30
31use super::{IntoPyObjectPoseiExt, to_pyvalue_err};
32use crate::uuid::{UUID4, UUID4_LEN};
33
34#[pymethods]
35impl UUID4 {
36 #[new]
41 fn py_new() -> Self {
42 Self::new()
43 }
44
45 #[allow(clippy::needless_pass_by_value)]
47 fn __setstate__(&mut self, py: Python<'_>, state: PyObject) -> PyResult<()> {
48 let bytes: &Bound<'_, PyBytes> = state.downcast_bound::<PyBytes>(py)?;
49 let slice = bytes.as_bytes();
50
51 if slice.len() != UUID4_LEN {
52 return Err(to_pyvalue_err(
53 "Invalid state for deserialzing, incorrect bytes length",
54 ));
55 }
56
57 self.value.copy_from_slice(slice);
58 Ok(())
59 }
60
61 fn __getstate__(&self, py: Python<'_>) -> PyResult<PyObject> {
63 PyBytes::new(py, &self.value).into_py_any(py)
64 }
65
66 fn __reduce__(&self, py: Python<'_>) -> PyResult<PyObject> {
68 let safe_constructor = py.get_type::<Self>().getattr("_safe_constructor")?;
69 let state = self.__getstate__(py)?;
70 (safe_constructor, PyTuple::empty(py), state).into_py_any(py)
71 }
72
73 #[staticmethod]
75 #[allow(clippy::unnecessary_wraps)]
76 fn _safe_constructor() -> PyResult<Self> {
77 Ok(Self::new()) }
79
80 fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py<PyAny> {
82 match op {
83 CompareOp::Eq => self.eq(other).into_py_any_unwrap(py),
84 CompareOp::Ne => self.ne(other).into_py_any_unwrap(py),
85 _ => py.NotImplemented(),
86 }
87 }
88
89 #[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
91 fn __hash__(&self) -> isize {
92 let mut h = DefaultHasher::new();
93 self.hash(&mut h);
94 h.finish() as isize
95 }
96
97 fn __repr__(&self) -> String {
99 format!("{self:?}")
100 }
101
102 fn __str__(&self) -> String {
104 self.to_string()
105 }
106
107 #[getter]
109 #[pyo3(name = "value")]
110 fn py_value(&self) -> String {
111 self.to_string()
112 }
113
114 #[staticmethod]
116 #[pyo3(name = "from_str")]
117 fn py_from_str(value: &str) -> PyResult<Self> {
118 Self::from_str(value).map_err(to_pyvalue_err)
119 }
120}