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}