Skip to main content

dune_raw/
types.rs

1/// Vector type, as named in the rawfile `Variables:` table.
2///
3/// The canonical names come from the `types[]` table in
4/// `corpus/spice3f5/src/lib/fte/types.c`. The type is stored *by name*,
5/// not by the `SV_*` index: the 3f5 table and the `SV_*` constants in
6/// `fteconst.h` disagree from index 5 on (the table kept four noise
7/// entries the constants collapsed into two), so round-tripping the name
8/// is the only unambiguous representation.
9#[derive(Clone, Debug, PartialEq, Eq)]
10pub enum VarType {
11    NoType,
12    Time,
13    Frequency,
14    Voltage,
15    Current,
16    OnoiseSpectrum,
17    OnoiseIntegrated,
18    InoiseSpectrum,
19    InoiseIntegrated,
20    OutputNoise,
21    InputNoise,
22    Pole,
23    Zero,
24    SParam,
25    /// A name not in the 3f5 table (e.g. ngspice additions). Kept
26    /// verbatim so writing it back is lossless.
27    Other(String),
28}
29
30impl VarType {
31    /// The name written in the `Variables:` table (`ft_typenames`).
32    pub fn name(&self) -> &str {
33        match self {
34            VarType::NoType => "notype",
35            VarType::Time => "time",
36            VarType::Frequency => "frequency",
37            VarType::Voltage => "voltage",
38            VarType::Current => "current",
39            VarType::OnoiseSpectrum => "onoise-spectrum",
40            VarType::OnoiseIntegrated => "onoise-integrated",
41            VarType::InoiseSpectrum => "inoise-spectrum",
42            VarType::InoiseIntegrated => "inoise-integrated",
43            VarType::OutputNoise => "output-noise",
44            VarType::InputNoise => "input-noise",
45            VarType::Pole => "pole",
46            VarType::Zero => "zero",
47            VarType::SParam => "s-param",
48            VarType::Other(s) => s,
49        }
50    }
51
52    /// Case-insensitive lookup (`ft_typnum`); unknown names are kept.
53    pub fn from_name(name: &str) -> Self {
54        const TABLE: [(&str, VarType); 14] = [
55            ("notype", VarType::NoType),
56            ("time", VarType::Time),
57            ("frequency", VarType::Frequency),
58            ("voltage", VarType::Voltage),
59            ("current", VarType::Current),
60            ("onoise-spectrum", VarType::OnoiseSpectrum),
61            ("onoise-integrated", VarType::OnoiseIntegrated),
62            ("inoise-spectrum", VarType::InoiseSpectrum),
63            ("inoise-integrated", VarType::InoiseIntegrated),
64            ("output-noise", VarType::OutputNoise),
65            ("input-noise", VarType::InputNoise),
66            ("pole", VarType::Pole),
67            ("zero", VarType::Zero),
68            ("s-param", VarType::SParam),
69        ];
70        for (n, t) in TABLE {
71            if n.eq_ignore_ascii_case(name) {
72                return t;
73            }
74        }
75        VarType::Other(name.to_owned())
76    }
77
78    /// Unit abbreviation (`ft_typabbrev`), used by the reader to rename
79    /// vectors whose name starts with a digit: `2` of type voltage
80    /// becomes `V(2)`.
81    pub fn abbrev(&self) -> Option<&'static str> {
82        match self {
83            VarType::Time => Some("S"),
84            VarType::Frequency => Some("Hz"),
85            VarType::Voltage => Some("V"),
86            VarType::Current => Some("A"),
87            VarType::OnoiseSpectrum | VarType::InoiseSpectrum => Some("(V or A)^2/Hz"),
88            VarType::OnoiseIntegrated | VarType::InoiseIntegrated => Some("V or A"),
89            _ => None,
90        }
91    }
92}
93
94#[cfg(test)]
95mod tests {
96    use super::*;
97
98    #[test]
99    fn roundtrip_names() {
100        for name in [
101            "notype",
102            "time",
103            "frequency",
104            "voltage",
105            "current",
106            "onoise-spectrum",
107            "s-param",
108        ] {
109            assert_eq!(VarType::from_name(name).name(), name);
110        }
111    }
112
113    #[test]
114    fn case_insensitive_and_unknown() {
115        assert_eq!(VarType::from_name("VOLTAGE"), VarType::Voltage);
116        assert_eq!(
117            VarType::from_name("admittance"),
118            VarType::Other("admittance".into())
119        );
120        assert_eq!(VarType::from_name("admittance").name(), "admittance");
121    }
122}