#![allow(clippy::unsafe_derive_deserialize, clippy::undocumented_unsafe_blocks)]
use crate::{
Ctx,
ast::{CodeFormatter, ComplexAttri, ComplexParseError, Indentation, ParseScope},
common::{f64_into_hash_ord_fn, parse_f64},
};
use core::{
cmp::Ordering,
fmt::{self, Write},
};
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[derive(strum::EnumString, strum::Display, strum::IntoStaticStr, strum::EnumIter)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum TimeUnit {
#[strum(serialize = "1ps")]
_1ps,
#[strum(serialize = "10ps")]
_10ps,
#[strum(serialize = "100ps")]
_100ps,
#[default]
#[strum(serialize = "1ns")]
_1ns,
}
impl TimeUnit {
#[inline]
#[must_use]
pub const fn value(&self) -> f64 {
match self {
Self::_1ps => 1E-12_f64,
Self::_10ps => 1E-11_f64,
Self::_100ps => 1E-10_f64,
Self::_1ns => 1E-9_f64,
}
}
}
crate::ast::impl_self_builder!(TimeUnit);
crate::ast::impl_simple!(TimeUnit);
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[derive(strum::EnumString, strum::Display, strum::IntoStaticStr, strum::EnumIter)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum VoltageUnit {
#[strum(serialize = "1mV")]
_1mV,
#[strum(serialize = "10mV")]
_10mV,
#[strum(serialize = "100mV")]
_100mV,
#[default]
#[strum(serialize = "1V")]
_1V,
}
impl VoltageUnit {
#[inline]
#[must_use]
pub const fn value(&self) -> f64 {
match self {
Self::_1mV => 1E-3_f64,
Self::_10mV => 1E-2_f64,
Self::_100mV => 1E-1_f64,
Self::_1V => 1E0_f64,
}
}
}
crate::ast::impl_self_builder!(VoltageUnit);
crate::ast::impl_simple!(VoltageUnit);
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[derive(strum::EnumString, strum::Display, strum::IntoStaticStr, strum::EnumIter)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum CurrentUnit {
#[strum(serialize = "1uA")]
_1uA,
#[strum(serialize = "10uA")]
_10uA,
#[strum(serialize = "100uA")]
_100uA,
#[strum(serialize = "1mA")]
_1mA,
#[strum(serialize = "10mA")]
_10mA,
#[strum(serialize = "100mA")]
_100mA,
#[strum(serialize = "1A")]
_1A,
}
impl CurrentUnit {
#[inline]
#[must_use]
pub const fn value(&self) -> f64 {
match self {
Self::_1uA => 1E-6_f64,
Self::_10uA => 1E-5_f64,
Self::_100uA => 1E-4_f64,
Self::_1mA => 1E-3_f64,
Self::_10mA => 1E-2_f64,
Self::_100mA => 1E-1_f64,
Self::_1A => 1E0_f64,
}
}
}
crate::ast::impl_self_builder!(CurrentUnit);
crate::ast::impl_simple!(CurrentUnit);
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[derive(strum::EnumString, strum::Display, strum::IntoStaticStr, strum::EnumIter)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum PullingResistanceUnit {
#[strum(serialize = "1ohm")]
_1ohm,
#[strum(serialize = "10ohm")]
_10ohm,
#[strum(serialize = "100ohm")]
_100ohm,
#[strum(serialize = "1kohm")]
_1kohm,
}
impl PullingResistanceUnit {
#[inline]
#[must_use]
pub const fn value(&self) -> f64 {
match self {
Self::_1ohm => 1E0_f64,
Self::_10ohm => 1E1_f64,
Self::_100ohm => 1E2_f64,
Self::_1kohm => 1E3_f64,
}
}
}
crate::ast::impl_self_builder!(PullingResistanceUnit);
crate::ast::impl_simple!(PullingResistanceUnit);
#[derive(Debug, Clone, Copy)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum CapacitiveLoadUnit {
FF(f64),
PF(f64),
}
impl Default for CapacitiveLoadUnit {
#[inline]
fn default() -> Self {
Self::_1pf
}
}
impl PartialEq for CapacitiveLoadUnit {
#[inline]
fn eq(&self, other: &Self) -> bool {
f64_into_hash_ord_fn(&self.value()) == f64_into_hash_ord_fn(&other.value())
}
}
impl fmt::Display for CapacitiveLoadUnit {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::FF(val) => write!(f, "{val} ff"),
Self::PF(val) => write!(f, "{val} pf"),
}
}
}
impl Eq for CapacitiveLoadUnit {}
impl PartialOrd for CapacitiveLoadUnit {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for CapacitiveLoadUnit {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
f64_into_hash_ord_fn(&self.value()).cmp(&f64_into_hash_ord_fn(&other.value()))
}
}
impl CapacitiveLoadUnit {
#[expect(non_upper_case_globals)]
pub const _1pf: Self = Self::PF(1.0);
#[expect(non_upper_case_globals)]
pub const _1ff: Self = Self::FF(1.0);
#[inline]
#[must_use]
#[expect(clippy::float_arithmetic)]
pub fn value(&self) -> f64 {
match self {
Self::FF(val) => val * 1e-15,
Self::PF(val) => val * 1e-12,
}
}
}
crate::ast::impl_self_builder!(CapacitiveLoadUnit);
impl<C: Ctx> ComplexAttri<C> for CapacitiveLoadUnit {
#[inline]
fn parse<'a, I: Iterator<Item = &'a &'a str>>(
mut iter: I,
_scope: &mut ParseScope<'_>,
) -> Result<Self, ComplexParseError> {
let val = match iter.next() {
Some(s) => parse_f64(s)?,
None => return Err(ComplexParseError::LengthDismatch),
};
let out = match iter.next() {
Some(&s) => match s {
"ff" => Self::FF(val),
"pf" => Self::PF(val),
_ => return Err(ComplexParseError::UnsupportedWord),
},
None => return Err(ComplexParseError::LengthDismatch),
};
if iter.next().is_some() {
return Err(ComplexParseError::LengthDismatch);
}
Ok(out)
}
#[inline]
fn fmt_self<T: Write, I: Indentation>(
&self,
f: &mut CodeFormatter<'_, T, I>,
) -> fmt::Result {
match *self {
Self::FF(val) => {
f.write_num(val)?;
f.write_str(", ff")
}
Self::PF(val) => {
f.write_num(val)?;
f.write_str(", pf")
}
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[derive(strum::EnumString, strum::Display, strum::IntoStaticStr, strum::EnumIter)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum LeakagePowerUnit {
#[strum(serialize = "1pW")]
_1pW,
#[strum(serialize = "10pW")]
_10pW,
#[strum(serialize = "100pW")]
_100pW,
#[strum(serialize = "1nW")]
_1nW,
#[strum(serialize = "10nW")]
_10nW,
#[strum(serialize = "100nW")]
_100nW,
#[strum(serialize = "1uW")]
_1uW,
#[strum(serialize = "10uW")]
_10uW,
#[strum(serialize = "100uW")]
_100uW,
#[strum(serialize = "1mW")]
_1mW,
#[strum(serialize = "10mW")]
_10mW,
#[strum(serialize = "100mW")]
_100mW,
#[strum(serialize = "1W")]
_1W,
}
impl LeakagePowerUnit {
#[inline]
#[must_use]
pub const fn value(&self) -> f64 {
match self {
Self::_1pW => 1E-12_f64,
Self::_10pW => 1E-11_f64,
Self::_100pW => 1E-10_f64,
Self::_1nW => 1E-9_f64,
Self::_10nW => 1E-8_f64,
Self::_100nW => 1E-7_f64,
Self::_1uW => 1E-6_f64,
Self::_10uW => 1E-5_f64,
Self::_100uW => 1E-4_f64,
Self::_1mW => 1E-3_f64,
Self::_10mW => 1E-2_f64,
Self::_100mW => 1E-1_f64,
Self::_1W => 1E-0_f64,
}
}
}
crate::ast::impl_self_builder!(LeakagePowerUnit);
crate::ast::impl_simple!(LeakagePowerUnit);