use crate::Ome; use crate::ome::{ Convert, UnitsElectricPotential, UnitsFrequency, UnitsLength, UnitsPower, UnitsPressure, UnitsTemperature, UnitsTime, }; use pyo3::exceptions::PyValueError; use pyo3::prelude::*; macro_rules! impl_enum_into_py_object { ($($s:ident: $t:ty $(,)?)*) => { $( #[pyclass(module = "ome_metadata.ome_metadata_rs")] pub struct $s { inner: $t, } #[pymethods] impl $s { #[new] fn new(unit: &str) -> PyResult { match unit.parse() { Ok(unit) => Ok(Self { inner: unit }), Err(_) => Err(PyErr::new::(format!("Invalid unit: {}", unit))) } } /// convert a value between units fn convert(&self, unit: &str, value: f64) -> PyResult { match unit.parse() { Ok(unit) => Ok(self.inner.convert(&unit, value).map_err(|e| PyErr::new::(format!("{}", e)))?), Err(_) => Err(PyErr::new::(format!("Invalid unit: {}", unit))) } } /// all possible variants of this enum that can be constructed or converted into #[staticmethod] fn variants() -> Vec { <$t>::variants().iter().map(|v| format!("{:?}", v)).collect() } fn __repr__(&self) -> String { format!("{:?}", self.inner) } fn __str__(&self) -> String { format!("{:?}", self.inner) } fn __getnewargs__(&self) -> (String,) { (format!("{:?}", self.inner),) } } impl<'py> IntoPyObject<'py> for $t { type Target = $s; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> PyResult { Bound::new(py, $s { inner: self }) } } )* }; } impl_enum_into_py_object! { ElectricPotential: UnitsElectricPotential Frequency: UnitsFrequency Length: UnitsLength Power: UnitsPower Pressure: UnitsPressure Temperature: UnitsTemperature Time: UnitsTime } #[pymodule] #[pyo3(name = "ome_metadata_rs")] fn ome_metadata_rs(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::