ipmi_rs/storage/sdr/
units.rs

1pub trait IsPlural: PartialEq {
2    fn is_singular(&self) -> bool;
3    fn is_plural(&self) -> bool {
4        !self.is_singular()
5    }
6}
7
8macro_rules ! impl_is_singular {
9    ($($ty:ty: [$pos:literal$(, $neg:literal)?]),*) => {
10        $(
11            impl IsPlural for $ty {
12                fn is_singular(&self) -> bool {
13                    if self == &$pos {
14                        true
15                    }
16                    $(
17                        else if self == &$neg {
18                            true
19                        }
20                    )?
21                     else {
22                        false
23                     }
24                }
25            }
26        )*
27    }
28}
29
30impl_is_singular!(
31    u8: [1],
32    u16: [1],
33    u32: [1],
34    u64: [1],
35    u128: [1],
36    i8: [1, -1],
37    i16: [1, -1],
38    i32: [1, -1],
39    i64: [1, -1],
40    i128: [1, -1],
41    f32: [1.0, -1.0],
42    f64: [1.0, -1.0]
43);
44
45macro_rules ! unit {
46    {
47        $($name:ident = [$value:literal, $short:expr, $singular:literal, $plural:literal],)*
48    } => {
49        #[derive(Debug, Clone, Copy, PartialEq)]
50        #[repr(u8)]
51        pub enum Unit {
52            $($name = $value,)*
53            Unknown(u8),
54        }
55
56        impl Unit {
57            fn short_display(&self) -> Option<&str> {
58                match self {
59                    $(Self::$name => $short,)*
60                    Self::Unknown(_) => None,
61                }
62            }
63
64            fn plural_display(&self) -> &str {
65                match self {
66                    $(Self::$name => $plural,)*
67                    Self::Unknown(_) => "Unknown",
68                }
69            }
70
71            fn singular_display(&self) -> &str {
72                match self {
73                    $(Self::$name => $singular,)*
74                    Self::Unknown(_) => "Unknown",
75                }
76            }
77
78            fn display_str(&self, short: bool, plural: bool) -> &str
79            {
80                let short_value = if short {
81                    self.short_display()
82                } else {
83                    None
84                };
85
86                if let Some(short_value) = short_value {
87                    short_value
88                } else {
89                    if plural {
90                        self.plural_display()
91                    } else {
92                        self.singular_display()
93                    }
94                }
95            }
96
97            pub fn display<T>(&self, short: bool, value: T) -> String
98                where T: IsPlural + core::fmt::Display,
99            {
100                format!("{:.2} {}", value, self.display_str(short, value.is_plural()))
101            }
102        }
103
104        impl From<u8> for Unit {
105            fn from(value: u8) -> Self {
106                match value {
107                    $($value => Self::$name,)*
108                    _ => Self::Unknown(value),
109                }
110            }
111        }
112
113        impl From<Unit> for u8 {
114            fn from(value: Unit) -> Self {
115                match value {
116                    $(Unit::$name => $value,)*
117                    Unit::Unknown(v) => v,
118                }
119            }
120        }
121
122    }
123}
124
125unit! {
126    Unspecified = [0, None, "Unspecified", "Unspecified"],
127    DegreesCelcius = [1, Some("°C"), "Degree Celcius", "Degrees Celcius"],
128    DegreesFahrenheit = [2, Some("°F"), "Degree Fahrenheit", "Degrees Fahrenheit"],
129    DegreesKelvin = [3, Some("°K"), "Degree Kelvin", "Degrees Kelvin"],
130    Volt = [4, Some("V"), "Volt", "Volts"],
131    Amp = [5, Some("A"), "Ampere", "Amperes"],
132    Watt = [6, Some("W"), "Watt", "Watts"],
133    Joule = [7, Some("J"), "Joule", "Joules"],
134    Coulomb = [8, Some("C"), "Coulomb", "Coulombs"],
135    VoltAmpere = [9, Some("VA"), "Volt-Ampere", "Volt-Amperes"],
136    Nit = [10, None, "Nit", "Nits"],
137    Lumen = [11, Some("lm"), "Lumen", "Lumens"],
138    Lux = [12, Some("lx"), "Lux", "Lux"],
139    Candela = [13, Some("cd"), "Candela", "Candelas"],
140    KiloPascal = [14, Some("kPa"), "Kilopascal", "Kilopascal"],
141    PoundsPerSquareInch = [15, Some("psi"), "Pound per square inch", "Pounds per square inch"],
142    Newton = [16, Some("N"), "Newton", "Newton"],
143    CubicFeetPerMinute = [17, Some("cfm"), "Cubic Foot per Minute", "Cubic Feet per minute"],
144    RevolutionsPerMinute = [18, Some("rpm"), "Revolution per Minute", "Revolutions per Minute"],
145    Hertz = [19, Some("hz"), "Hertz", "Hertz"],
146    Microsecond = [20, Some("µs"), "Microsecond", "Microseconds"],
147    Millisecond = [21, Some("ms"), "Millisecond", "Milliseconds"],
148    Second = [22, Some("s"), "Second", "Seconds"],
149    Minute = [23, Some("min"), "Minute", "Minutes"],
150    Hour = [24, Some("h"), "Hour", "Hours"],
151    Day = [25, Some("d"), "Day", "Days"],
152    Week = [26, Some("w"), "Week", "Weeks"],
153    Mil = [27, Some("mil"), "mil", "mils"],
154    Inch = [28, Some("in"), "Inch", "Inches"],
155    Foot = [29, Some("ft"), "Foot", "Feet"],
156    CubicInch = [30, Some("cu in"), "Cubic Inch", "Cubic Inches"],
157    CubicFoot = [31, Some("cu ft"), "Cubic Foot", "Cubic Feet"],
158    Millimeter = [32, Some("mm"), "Millimeter", "Millimeters"],
159    Centimeter = [33, Some("cm"), "Centimeter", "Centimeters"],
160    Meter = [34, Some("m"), "Meter", "Meters"],
161    CubicCentimeter = [35, Some("cu cm"), "Cubic Centimeter", "Cubic Centimeters"],
162    CubicMeter = [36, Some("cu m"), "Cubic Meter", "Cubic Meters"],
163    Liter = [37, Some("l"), "Liter", "Liters"],
164    FluidOunce = [38, Some("fl oz"), "Fluid Ounce", "Fluid Ounces"],
165    Radian = [39, Some("rad"), "Radian", "Radians"],
166    Steradian = [40, Some("sr"), "Steradian", "Steradians"],
167    Revolution = [41, Some("rev"), "Revolution", "Revolutions"],
168    Cycle = [42, None, "Cycle", "Cycles"],
169    Gravity = [43, Some("Gs (grav)"), "Gravity", "Gravities"],
170    Ounce = [44, Some("oz"), "Ounce", "Ounces"],
171    Pound = [45, Some("lb"), "Pound", "Pounds"],
172    FootPound = [46, Some("ft lb"), "Foot Pound", "Foot Pounds"],
173    OunceInch = [47, Some("oz in"), "Ounce Inch", "Ounce Inches"],
174    Gauss = [48, Some("Gs"), "Gauss", "Gauss"],
175    Gilbert = [49, Some("Gb"), "Gilbert", "Gilbert"],
176    Henry = [50, Some("H"), "Heny", "Heny"],
177    Millihenry = [51, Some("mH"), "Millihenry", "Millihenry"],
178    Farad = [52, Some("F"), "Farad", "Farad"],
179    Microfarad = [53, Some("µF"), "Microfarad", "Microfarad"],
180    Ohm = [54, Some("Ω"), "Ohm", "Ohm"],
181    Siemens = [55, Some("S"), "Siemens", "Siemens"],
182    Mole = [56, Some("mol"), "Mol", "Mol"],
183    Becquerel = [57, Some("Bq"), "Becquerel", "Becquerel"],
184    PartsPerMillion = [58, Some("ppm"), "Part part per million", "Parts per million"],
185    Decibel = [60, Some("dB"), "Decibel", "Decibels"],
186    AWeightedDecibel = [61, Some("dBa"), "A weighted Decibel", "A weighted Decibels"],
187    CWeightedDecibel = [62, Some("dBc"), "C weighted Decibel", "C weighted Decibels"],
188    Gray = [63, Some("Gy"), "Gray", "Gray"],
189    Sievert = [64, Some("Sv"), "Sievert", "Sievert"],
190    ColorTemperatureDegreesKelvin = [65, Some("°K (Color)"), "Degree Kelvin (Color)", "Degrees Kelvin (Color)"],
191    Bit = [66, Some("b"), "Bit", "Bits"],
192    Kilobit = [67, Some("kb"), "Kilobit", "Kilobits"],
193    Megabit = [68, Some("mb"), "Megabit", "Megabits"],
194    Gigabit = [69, Some("Gb"), "Gigabit", "Gigabits"],
195    Byte = [70, Some("B"), "Byte", "Bytes"],
196    Kilobyte = [71, Some("KB"), "Kilobyte", "Kilobytes"],
197    Megabyte = [72, Some("MB"), "Megabyte", "Megabytes"],
198    Gigabyte = [73, Some("GB"), "Gigabyte", "Gigabytes"],
199    Word = [74, None, "Word", "Words"],
200    DoubleWord = [75, None, "Double word", "Double words"],
201    QuadWord = [76, None, "Quad word", "Quad words"],
202    CacheLine = [77, None, "Cache line", "Cache lines"],
203    Hit = [78, None, "Hit", "Hits"],
204    Miss = [79, None, "Miss", "Misses"],
205    Retry = [80, None, "Retry", "Retries"],
206    Reset = [81, None, "Reset", "Resets"],
207    OverrunOrUnderflow = [82, None, "Overrun or Underflow", "Overruns or Underflows"],
208    Underrun = [83, None, "Underrun", "Underruns"],
209    Collision = [84, None, "Collision", "Collisions"],
210    Packet = [85, None, "Packet", "Packets"],
211    Message = [86, None, "Message", "Messges"],
212    Character = [87, None, "Character", "Characters"],
213    Error = [88, None, "Error", "Errors"],
214    CorrectableError = [89, None, "Correctable Error", "Correctable Errors"],
215    UncorrectableError = [90, None, "Uncorrectable Error", "Uncorrectable Errors"],
216    FatalError = [91, None, "Fatal Error", "Fatal Errors"],
217    Gram = [92, Some("gr"), "Gram", "Grams"],
218}
219
220#[test]
221fn display_tests() {
222    use Unit::*;
223
224    assert_eq!("32 °C", DegreesCelcius.display(true, 32));
225    assert_eq!("32 Degrees Celcius", DegreesCelcius.display(false, 32));
226    assert_eq!("1 Degree Celcius", DegreesCelcius.display(false, 1));
227    assert_eq!("-1 Nit", Nit.display(true, -1));
228    assert_eq!("-1 Nit", Nit.display(false, -1));
229    assert_eq!("-15 Nits", Nit.display(false, -15));
230}