#![allow(clippy::unsafe_derive_deserialize, clippy::undocumented_unsafe_blocks)]
use crate::{
ast::{
CodeFormatter, ComplexAttri, ComplexParseError, Indentation, ParseScope, SimpleAttri,
},
common::parse_f64,
NotNan,
};
use core::fmt::{self, Write};
#[derive(Debug, Default, Clone, Copy)]
#[derive(strum_macros::EnumString, strum_macros::Display)]
#[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) -> NotNan<f64> {
match self {
Self::_1ps => unsafe { NotNan::new_unchecked(1E-12_f64) },
Self::_10ps => unsafe { NotNan::new_unchecked(1E-11_f64) },
Self::_100ps => unsafe { NotNan::new_unchecked(1E-10_f64) },
Self::_1ns => unsafe { NotNan::new_unchecked(1E-9_f64) },
}
}
}
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)]
#[derive(strum_macros::EnumString, strum_macros::Display)]
#[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) -> NotNan<f64> {
match self {
Self::_1mV => unsafe { NotNan::new_unchecked(1E-3_f64) },
Self::_10mV => unsafe { NotNan::new_unchecked(1E-2_f64) },
Self::_100mV => unsafe { NotNan::new_unchecked(1E-1_f64) },
Self::_1V => unsafe { NotNan::new_unchecked(1E0_f64) },
}
}
}
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)]
#[derive(strum_macros::EnumString, strum_macros::Display)]
#[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) -> NotNan<f64> {
match self {
Self::_1uA => unsafe { NotNan::new_unchecked(1E-6_f64) },
Self::_10uA => unsafe { NotNan::new_unchecked(1E-5_f64) },
Self::_100uA => unsafe { NotNan::new_unchecked(1E-4_f64) },
Self::_1mA => unsafe { NotNan::new_unchecked(1E-3_f64) },
Self::_10mA => unsafe { NotNan::new_unchecked(1E-2_f64) },
Self::_100mA => unsafe { NotNan::new_unchecked(1E-1_f64) },
Self::_1A => unsafe { NotNan::new_unchecked(1E0_f64) },
}
}
}
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)]
#[derive(strum_macros::EnumString, strum_macros::Display)]
#[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) -> NotNan<f64> {
match self {
Self::_1ohm => unsafe { NotNan::new_unchecked(1E0_f64) },
Self::_10ohm => unsafe { NotNan::new_unchecked(1E1_f64) },
Self::_100ohm => unsafe { NotNan::new_unchecked(1E2_f64) },
Self::_1kohm => unsafe { NotNan::new_unchecked(1E3_f64) },
}
}
}
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, Default, Clone, Copy)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct CapacitiveLoadUnit {
pub ff_pf: bool,
pub val: NotNan<f64>,
}
impl CapacitiveLoadUnit {
#[inline]
#[must_use]
#[expect(clippy::arithmetic_side_effects, clippy::float_arithmetic)]
pub fn value(&self) -> NotNan<f64> {
if self.ff_pf {
self.val * 1e-15
} else {
self.val * 1e-12
}
}
}
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_float(self.val.into_inner())?;
if self.ff_pf {
f.write_str(", ff")
} else {
f.write_str(", pf")
}
}
}
#[derive(Debug, Clone, Copy)]
#[derive(strum_macros::EnumString, strum_macros::Display)]
#[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) -> NotNan<f64> {
match self {
Self::_1pW => unsafe { NotNan::new_unchecked(1E-12_f64) },
Self::_10pW => unsafe { NotNan::new_unchecked(1E-11_f64) },
Self::_100pW => unsafe { NotNan::new_unchecked(1E-10_f64) },
Self::_1nW => unsafe { NotNan::new_unchecked(1E-9_f64) },
Self::_10nW => unsafe { NotNan::new_unchecked(1E-8_f64) },
Self::_100nW => unsafe { NotNan::new_unchecked(1E-7_f64) },
Self::_1uW => unsafe { NotNan::new_unchecked(1E-6_f64) },
Self::_10uW => unsafe { NotNan::new_unchecked(1E-5_f64) },
Self::_100uW => unsafe { NotNan::new_unchecked(1E-4_f64) },
Self::_1mW => unsafe { NotNan::new_unchecked(1E-3_f64) },
Self::_10mW => unsafe { NotNan::new_unchecked(1E-2_f64) },
Self::_100mW => unsafe { NotNan::new_unchecked(1E-1_f64) },
Self::_1W => unsafe { NotNan::new_unchecked(1E-0_f64) },
}
}
}
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)
}
}