#![allow(clippy::unsafe_derive_deserialize, clippy::undocumented_unsafe_blocks)]
use crate::{
ast::{
CodeFormatter, ComplexAttri, ComplexParseError, Indentation, ParseScope, SimpleAttri,
},
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_macros::EnumString, strum_macros::Display, strum_macros::AsRefStr)]
#[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);
impl SimpleAttri for TimeUnit {
#[inline]
fn nom_parse<'a>(
i: &'a str,
scope: &mut ParseScope,
) -> crate::ast::SimpleParseRes<'a, Self> {
crate::ast::nom_parse_from_str(i, scope)
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[derive(strum_macros::EnumString, strum_macros::Display, strum_macros::AsRefStr)]
#[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);
impl SimpleAttri for VoltageUnit {
#[inline]
fn nom_parse<'a>(
i: &'a str,
scope: &mut ParseScope,
) -> crate::ast::SimpleParseRes<'a, Self> {
crate::ast::nom_parse_from_str(i, scope)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[derive(strum_macros::EnumString, strum_macros::Display, strum_macros::AsRefStr)]
#[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);
impl SimpleAttri for CurrentUnit {
#[inline]
fn nom_parse<'a>(
i: &'a str,
scope: &mut ParseScope,
) -> crate::ast::SimpleParseRes<'a, Self> {
crate::ast::nom_parse_from_str(i, scope)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[derive(strum_macros::EnumString, strum_macros::Display, strum_macros::AsRefStr)]
#[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);
impl SimpleAttri for PullingResistanceUnit {
#[inline]
fn nom_parse<'a>(
i: &'a str,
scope: &mut ParseScope,
) -> crate::ast::SimpleParseRes<'a, Self> {
crate::ast::nom_parse_from_str(i, scope)
}
}
#[derive(Debug, Clone, Copy)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct CapacitiveLoadUnit {
pub ff_pf: bool,
pub val: 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 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 { ff_pf: false, val: 1.0 };
#[inline]
#[must_use]
#[expect(clippy::float_arithmetic)]
pub fn value(&self) -> f64 {
if self.ff_pf {
self.val * 1e-15
} else {
self.val * 1e-12
}
}
}
crate::ast::impl_self_builder!(CapacitiveLoadUnit);
impl ComplexAttri 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 ff_pf = match iter.next() {
Some(&s) => match s {
"ff" => true,
"pf" => false,
_ => return Err(ComplexParseError::UnsupportedWord),
},
None => return Err(ComplexParseError::LengthDismatch),
};
if iter.next().is_some() {
return Err(ComplexParseError::LengthDismatch);
}
Ok(Self { ff_pf, val })
}
#[inline]
fn fmt_self<T: Write, I: Indentation>(
&self,
f: &mut CodeFormatter<'_, T, I>,
) -> fmt::Result {
f.write_num(self.val)?;
if self.ff_pf {
f.write_str(", ff")
} else {
f.write_str(", pf")
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[derive(strum_macros::EnumString, strum_macros::Display, strum_macros::AsRefStr)]
#[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);
impl SimpleAttri for LeakagePowerUnit {
#[inline]
fn nom_parse<'a>(
i: &'a str,
scope: &mut ParseScope,
) -> crate::ast::SimpleParseRes<'a, Self> {
crate::ast::nom_parse_from_str(i, scope)
}
}