implement conversions for units
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ome-metadata"
|
name = "ome-metadata"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
rust-version = "1.85.1"
|
rust-version = "1.85.1"
|
||||||
authors = ["Wim Pomp <w.pomp@nki.nl>"]
|
authors = ["Wim Pomp <w.pomp@nki.nl>"]
|
||||||
@@ -20,6 +20,7 @@ crate-type = ["cdylib", "rlib"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.98"
|
anyhow = "1.0.98"
|
||||||
|
enum-utils = "0.1.2"
|
||||||
serde = { version = "1.0.219", features = ["derive"] }
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
quick-xml = { version = "0.37.5", features = ["serialize"] }
|
quick-xml = { version = "0.37.5", features = ["serialize"] }
|
||||||
|
|
||||||
|
|||||||
622
src/ome.rs
622
src/ome.rs
File diff suppressed because it is too large
Load Diff
115
src/py.rs
115
src/py.rs
@@ -1,9 +1,124 @@
|
|||||||
|
use anyhow::anyhow;
|
||||||
use crate::Ome;
|
use crate::Ome;
|
||||||
|
use crate::ome::{
|
||||||
|
Convert, UnitsElectricPotential, UnitsFrequency, UnitsLength, UnitsPower,
|
||||||
|
UnitsPressure, UnitsTemperature, UnitsTime,
|
||||||
|
};
|
||||||
|
use pyo3::exceptions::PyValueError;
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
use pyo3::IntoPyObjectExt;
|
||||||
|
|
||||||
|
/// helper class to be used for unpickling
|
||||||
|
#[pyclass(module = "ome_metadata.ome_metadata_rs")]
|
||||||
|
struct Constructor;
|
||||||
|
|
||||||
|
#[pymethods]
|
||||||
|
impl Constructor {
|
||||||
|
#[new]
|
||||||
|
fn new() -> Self {
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __getstate__(&self) -> (u8,) {
|
||||||
|
(0,)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __setstate__(&self, _state: (u8,)) {}
|
||||||
|
|
||||||
|
#[staticmethod]
|
||||||
|
fn __call__(py: Python, class: String, variant: String) -> PyResult<Bound<PyAny>> {
|
||||||
|
match class.as_str() {
|
||||||
|
"ElectricPotential" => ElectricPotential::new(&variant)?.into_bound_py_any(py),
|
||||||
|
"Frequency" => Frequency::new(&variant)?.into_bound_py_any(py),
|
||||||
|
"Length" => Length::new(&variant)?.into_bound_py_any(py),
|
||||||
|
"Power" => Power::new(&variant)?.into_bound_py_any(py),
|
||||||
|
"Pressure" => Pressure::new(&variant)?.into_bound_py_any(py),
|
||||||
|
"Temperature" => Temperature::new(&variant)?.into_bound_py_any(py),
|
||||||
|
"Time" => Time::new(&variant)?.into_bound_py_any(py),
|
||||||
|
_ => Err(anyhow!("cannot parse class {}", class).into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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<Self> {
|
||||||
|
match unit.parse() {
|
||||||
|
Ok(unit) => Ok(Self { inner: unit }),
|
||||||
|
Err(_) => Err(PyErr::new::<PyValueError, _>(format!("Invalid unit: {}", unit)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// convert a value between units
|
||||||
|
fn convert(&self, unit: &str, value: f64) -> PyResult<f64> {
|
||||||
|
match unit.parse() {
|
||||||
|
Ok(unit) => Ok(self.inner.convert(&unit, value)?),
|
||||||
|
Err(_) => Err(PyErr::new::<PyValueError, _>(format!("Invalid unit: {}", unit)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// all possible variants of this enum that can be constructed or converted into
|
||||||
|
#[staticmethod]
|
||||||
|
fn variants() -> Vec<String> {
|
||||||
|
<$t>::variants().iter().map(|v| format!("{:?}", v)).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __repr__(&self) -> String {
|
||||||
|
format!("{:?}", self.inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __str__(&self) -> String {
|
||||||
|
format!("{:?}", self.inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __reduce__(&self) -> PyResult<(Constructor, (String, String))> {
|
||||||
|
Ok((Constructor, (stringify!($s).to_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<Self::Output> {
|
||||||
|
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]
|
#[pymodule]
|
||||||
#[pyo3(name = "ome_metadata_rs")]
|
#[pyo3(name = "ome_metadata_rs")]
|
||||||
fn ome_metadata_rs(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
fn ome_metadata_rs(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
||||||
|
m.add_class::<Constructor>()?;
|
||||||
|
m.add_class::<ElectricPotential>()?;
|
||||||
|
m.add_class::<Frequency>()?;
|
||||||
|
m.add_class::<Length>()?;
|
||||||
|
m.add_class::<Power>()?;
|
||||||
|
m.add_class::<Pressure>()?;
|
||||||
|
m.add_class::<Temperature>()?;
|
||||||
|
m.add_class::<Time>()?;
|
||||||
|
|
||||||
#[pyfn(m)]
|
#[pyfn(m)]
|
||||||
fn ome(text: &str) -> PyResult<Ome> {
|
fn ome(text: &str) -> PyResult<Ome> {
|
||||||
Ok(text.parse()?)
|
Ok(text.parse()?)
|
||||||
|
|||||||
Reference in New Issue
Block a user