liberty_db/
py.rs

1use pyo3::{prelude::*, types::PyTuple};
2use pyo3_stub_gen::{PyStubType, TypeInfo};
3
4use crate::{
5  cell::PgType,
6  expression::logic,
7  units::{
8    CapacitiveLoadUnit, CurrentUnit, LeakagePowerUnit, PullingResistanceUnit, TimeUnit,
9    VoltageUnit,
10  },
11};
12#[macro_export]
13macro_rules! impl_py_enum {
14  ($t:path) => {
15    impl<'py> FromPyObject<'_, 'py> for $t {
16      type Error = pyo3::PyErr;
17      #[inline]
18      fn extract(ob: pyo3::Borrowed<'_, 'py, PyAny>) -> PyResult<Self> {
19        match ob.extract::<alloc::borrow::Cow<'_, str>>()?.parse() {
20          Ok(t) => Ok(t),
21          Err(_) => {
22            Err(pyo3::exceptions::PyValueError::new_err("Matching variant not found"))
23          }
24        }
25      }
26    }
27    impl<'py> IntoPyObject<'py> for $t {
28      type Target = pyo3::types::PyString;
29      type Output = Bound<'py, Self::Target>;
30      type Error = PyErr;
31      #[inline]
32      fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
33        let s: &'static str = self.into();
34        Ok(pyo3::types::PyString::new(py, s))
35      }
36    }
37    impl PyStubType for $t {
38      #[inline]
39      fn type_output() -> TypeInfo {
40        use strum::IntoEnumIterator as _;
41        TypeInfo {
42          name: format!(
43            "typing.Literal{:?}",
44            Self::iter().into_iter().map(|t| t.to_string()).collect::<Vec<_>>()
45          ),
46          import: ["typing".into()].into_iter().collect(),
47        }
48      }
49    }
50  };
51}
52
53impl_py_enum!(logic::Edge);
54impl_py_enum!(TimeUnit);
55impl_py_enum!(VoltageUnit);
56impl_py_enum!(CurrentUnit);
57impl_py_enum!(PullingResistanceUnit);
58impl_py_enum!(LeakagePowerUnit);
59impl_py_enum!(PgType);
60
61impl<'py> FromPyObject<'_, 'py> for CapacitiveLoadUnit {
62  type Error = PyErr;
63
64  #[inline]
65  fn extract(obj: Borrowed<'_, 'py, PyAny>) -> PyResult<Self> {
66    let (val, s_ff_pf) = obj.extract::<(f64, String)>()?;
67    match s_ff_pf.as_str() {
68      "ff" => Ok(Self::FF(val)),
69      "pf" => Ok(Self::PF(val)),
70      _ => Err(pyo3::exceptions::PyValueError::new_err("Matching variant not found")),
71    }
72  }
73}
74impl<'py> IntoPyObject<'py> for CapacitiveLoadUnit {
75  type Target = PyTuple;
76  type Output = Bound<'py, Self::Target>;
77  type Error = PyErr;
78  #[inline]
79  fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
80    match self {
81      Self::FF(val) => (val, "ff"),
82      Self::PF(val) => (val, "pf"),
83    }
84    .into_pyobject(py)
85  }
86}
87impl PyStubType for CapacitiveLoadUnit {
88  #[inline]
89  fn type_output() -> TypeInfo {
90    TypeInfo::with_module(
91      "tuple[builtins.float, typing.Literal[\"ff\", \"pf\"]]",
92      "typing".into(),
93    )
94  }
95}