1use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
10pub enum LengthUnit {
11 Mils,
12 Mm,
13 Inches,
14 #[serde(rename = "um")]
15 Um,
16}
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
20pub enum FreqUnit {
21 Hz,
22 #[serde(rename = "kHz")]
23 KHz,
24 MHz,
25 GHz,
26}
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
30pub enum CapUnit {
31 F,
32 #[serde(rename = "uF")]
33 UF,
34 #[serde(rename = "nF")]
35 NF,
36 #[serde(rename = "pF")]
37 PF,
38}
39
40#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
42pub enum IndUnit {
43 H,
44 #[serde(rename = "mH")]
45 MH,
46 #[serde(rename = "uH")]
47 UH,
48 #[serde(rename = "nH")]
49 NH,
50}
51
52#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
54pub enum ResUnit {
55 #[serde(rename = "mOhm")]
56 MOhm,
57 Ohm,
58 #[serde(rename = "kOhm")]
59 KOhm,
60 #[serde(rename = "MOhm")]
61 MOhmMega,
62}
63
64#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
66pub enum TempUnit {
67 Celsius,
68 Fahrenheit,
69}
70
71pub fn to_mils(value: f64, unit: LengthUnit) -> f64 {
75 match unit {
76 LengthUnit::Mils => value,
77 LengthUnit::Mm => value / 0.0254,
78 LengthUnit::Inches => value * 1000.0,
79 LengthUnit::Um => value / 25.4,
80 }
81}
82
83pub fn from_mils(value: f64, unit: LengthUnit) -> f64 {
85 match unit {
86 LengthUnit::Mils => value,
87 LengthUnit::Mm => value * 0.0254,
88 LengthUnit::Inches => value / 1000.0,
89 LengthUnit::Um => value * 25.4,
90 }
91}
92
93pub fn to_hz(value: f64, unit: FreqUnit) -> f64 {
97 match unit {
98 FreqUnit::Hz => value,
99 FreqUnit::KHz => value * 1e3,
100 FreqUnit::MHz => value * 1e6,
101 FreqUnit::GHz => value * 1e9,
102 }
103}
104
105pub fn from_hz(value: f64, unit: FreqUnit) -> f64 {
107 match unit {
108 FreqUnit::Hz => value,
109 FreqUnit::KHz => value / 1e3,
110 FreqUnit::MHz => value / 1e6,
111 FreqUnit::GHz => value / 1e9,
112 }
113}
114
115pub fn to_farads(value: f64, unit: CapUnit) -> f64 {
119 match unit {
120 CapUnit::F => value,
121 CapUnit::UF => value * 1e-6,
122 CapUnit::NF => value * 1e-9,
123 CapUnit::PF => value * 1e-12,
124 }
125}
126
127pub fn from_farads(value: f64, unit: CapUnit) -> f64 {
129 match unit {
130 CapUnit::F => value,
131 CapUnit::UF => value / 1e-6,
132 CapUnit::NF => value / 1e-9,
133 CapUnit::PF => value / 1e-12,
134 }
135}
136
137pub fn to_henries(value: f64, unit: IndUnit) -> f64 {
141 match unit {
142 IndUnit::H => value,
143 IndUnit::MH => value * 1e-3,
144 IndUnit::UH => value * 1e-6,
145 IndUnit::NH => value * 1e-9,
146 }
147}
148
149pub fn from_henries(value: f64, unit: IndUnit) -> f64 {
151 match unit {
152 IndUnit::H => value,
153 IndUnit::MH => value / 1e-3,
154 IndUnit::UH => value / 1e-6,
155 IndUnit::NH => value / 1e-9,
156 }
157}
158
159pub fn to_celsius(value: f64, unit: TempUnit) -> f64 {
163 match unit {
164 TempUnit::Celsius => value,
165 TempUnit::Fahrenheit => (value - 32.0) * 5.0 / 9.0,
166 }
167}
168
169pub fn from_celsius(value: f64, unit: TempUnit) -> f64 {
171 match unit {
172 TempUnit::Celsius => value,
173 TempUnit::Fahrenheit => value * 9.0 / 5.0 + 32.0,
174 }
175}
176
177#[cfg(test)]
178mod tests {
179 use super::*;
180
181 #[test]
182 fn length_roundtrip() {
183 let mils = 100.0;
184 for unit in [LengthUnit::Mils, LengthUnit::Mm, LengthUnit::Inches, LengthUnit::Um] {
185 let converted = from_mils(mils, unit);
186 let back = to_mils(converted, unit);
187 assert!((back - mils).abs() < 1e-10, "roundtrip failed for {unit:?}");
188 }
189 }
190
191 #[test]
192 fn known_conversions() {
193 assert!((to_mils(0.0254, LengthUnit::Mm) - 1.0).abs() < 1e-10);
195 assert!((to_mils(1.0, LengthUnit::Inches) - 1000.0).abs() < 1e-10);
197 assert!((to_mils(25.4, LengthUnit::Um) - 1.0).abs() < 1e-10);
199 assert!((to_hz(1.0, FreqUnit::GHz) - 1e9).abs() < 1.0);
201 assert!((to_celsius(32.0, TempUnit::Fahrenheit)).abs() < 1e-10);
203 }
204}