Skip to main content

mzdata_param/
units.rs

1use std::fmt::Display;
2
3use crate::{CURIE, ControlledVocabulary, Param};
4
5/// Easily define all units. See the usage for more details. The accession and name both have to be
6/// included in `&'static str` and `byte slice` to allow for constant time matching.
7macro_rules! units {
8    [$($unit:ident, $accession:literal, $baccession:literal, $name:literal, $bname:literal, $cv:ident, $id:literal);*;] => {
9        /// Units that a term's value might have
10        #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
11        #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12        pub enum Unit {
13            Unknown,
14            $($unit,)*
15        }
16
17        impl Unit {
18            /// The `(accession, name)` pair for this unit's CV term, or `("", "")` for
19            /// [`Unit::Unknown`].
20            pub const fn for_param(&self) -> (&'static str, &'static str) {
21                match self {
22                    $(Self::$unit => ($accession, $name),)*
23                    Self::Unknown => ("","")
24                }
25            }
26
27            /// Look up a [`Unit`] by its CV term name (e.g. `"minute"`). Returns
28            /// [`Unit::Unknown`] if unrecognized.
29            pub const fn from_name(name: &str) -> Unit {
30                match name.as_bytes() {
31                    $($bname => Self::$unit,)*
32                    _ => Self::Unknown
33                }
34            }
35
36            /// Look up a [`Unit`] by its CV accession string (e.g. `"UO:0000031"`).
37            /// Returns [`Unit::Unknown`] if unrecognized.
38            pub const fn from_accession(acc: &str) -> Unit {
39                match acc.as_bytes() {
40                    $($baccession => Self::$unit,)*
41                    _ => Self::Unknown
42                }
43            }
44
45            /// Look up a [`Unit`] by its [`CURIE`]. Returns [`Unit::Unknown`] if
46            /// unrecognized.
47            pub const fn from_curie(acc: &CURIE) -> Unit {
48                match acc {
49                    $(CURIE {
50                        controlled_vocabulary: ControlledVocabulary::$cv,
51                        accession: $id,
52                    } => Self::$unit,)*
53                    _ => Self::Unknown
54                }
55            }
56
57            /// The [`CURIE`] for this unit's CV term, or `None` for [`Unit::Unknown`].
58            pub const fn to_curie(&self) -> Option<CURIE> {
59                match self {
60                    $(Self::$unit => Some(CURIE {
61                        controlled_vocabulary: ControlledVocabulary::$cv,
62                        accession: $id,
63                    }),)*
64                    Self::Unknown => None
65                }
66            }
67
68            /// Read the [`Param::unit`] of a [`Param`] directly.
69            pub const fn from_param(param: &Param) -> Unit {
70                param.unit
71            }
72
73            /// Check whether this is the [`Unit::Unknown`] sentinel.
74            pub const fn is_unknown(&self) -> bool {
75                matches!(self, Self::Unknown)
76            }
77        }
78    };
79}
80
81units![
82    AbsorbanceUnit, "UO:0000269", b"UO:0000269", "absorbance unit", b"absorbance unit", UO, 269;
83    Celsius, "UO:0000027", b"UO:0000027", "degree Celsius", b"degree Celsius", UO, 27;
84    CountsPerSecond, "MS:1000814", b"MS:1000814", "counts per second", b"counts per second", MS, 1000814;
85    DetectorCounts, "MS:1000131", b"MS:1000131", "number of detector counts", b"number of detector counts", MS, 1000131;
86    Dimensionless, "UO:0000186", b"UO:0000186", "dimensionless unit", b"dimensionless unit", UO, 186;
87    Electronvolt, "UO:0000266", b"UO:0000266", "electronvolt", b"electronvolt", UO, 266;
88    Kelvin, "UO:0000012", b"UO:0000012", "kelvin", b"kelvin", UO, 12;
89    Mass, "UO:000221", b"UO:000221", "dalton", b"dalton", UO, 221;
90    MicrolitersPerMinute, "UO:0000271", b"UO:0000271", "microliters per minute", b"microliters per minute", UO, 271;
91    Millisecond, "UO:0000028", b"UO:0000028", "millisecond", b"millisecond", UO, 28;
92    Minute, "UO:0000031", b"UO:0000031", "minute", b"minute", UO, 31;
93    MZ, "MS:1000040", b"MS:1000040", "m/z", b"m/z", MS, 1000040;
94    Nanometer, "UO:0000018", b"UO:0000018", "nanometer", b"nanometer", UO, 18;
95    Micrometer, "UO:0000017", b"UO:0000017", "micrometer", b"micrometer", UO, 17;
96    Millimeter, "UO:0000016", b"UO:0000016", "millimeter", b"millimeter", UO, 16;
97    Centimeter, "UO:0000015", b"UO:0000015", "centimeter", b"centimeter", UO, 15;
98    PartsPerMillion, "UO:0000169", b"UO:0000169", "parts per million ", b"parts per million ", UO, 169;
99    Pascal, "UO:0000110", b"UO:0000110", "pascal", b"pascal", UO, 110;
100    Percent, "UO:0000187", b"UO:0000187", "percent", b"percent", UO, 187;
101    PercentBasePeak, "MS:1000132", b"MS:1000132", "percent of base peak", b"percent of base peak", MS, 1000132;
102    PercentBasePeakTimes100, "MS:1000905", b"MS:1000905", "percent of base peak times 100", b"percent of base peak times 100", MS, 1000905;
103    Psi, "UO:0010052", b"UO:0010052", "pounds per square inch", b"pounds per square inch", UO, 10052;
104    Second, "UO:0000010", b"UO:0000010", "second", b"second", UO, 10;
105    Volt, "UO:0000218", b"UO:0000218", "volt", b"volt", UO, 218;
106    VoltSecondPerSquareCentimeter, "MS:1002814", b"MS:1002814", "volt-second per square centimeter", b"volt-second per square centimeter", MS, 1002814;
107    Hertz, "UO:000106", b"UO:000106", "hertz", b"hertz", UO, 106;
108    Liter, "UO:0000099", b"UO:0000099", "liter", b"liter", UO, 99;
109    Milliliter, "UO:0000098", b"UO:0000098", "milliliter", b"milliliter", UO, 98;
110    Microliter, "UO:0000101", b"UO:0000101", "microliter", b"microliter", UO, 101;
111];
112
113impl Default for Unit {
114    fn default() -> Self {
115        Self::Unknown
116    }
117}
118
119impl Display for Unit {
120    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
121        f.write_str(format!("{:?}", self).as_str())
122    }
123}