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