Skip to main content

cefact_units/
lib.rs

1//! UN/CEFACT Recommendation No. 20 — Codes for Units of Measure Used in
2//! International Trade (Revision 17, 2021).
3//!
4//! All data is generated at compile time from `rec20.xlsx` and embedded as
5//! `static` data. No runtime allocations, no I/O.
6//!
7//! # Example
8//!
9//! ```rust
10//! use cefact_units::UnitOfMeasure;
11//!
12//! let kg = UnitOfMeasure::from_code("KGM").unwrap();
13//! assert_eq!(kg.name(), "kilogram");
14//! assert_eq!(kg.symbol(), Some("kg"));
15//! assert_eq!(kg.quantity(), Some("mass"));
16//!
17//! let parsed: UnitOfMeasure = "MTR".parse().unwrap();
18//! assert_eq!(parsed.to_string(), "MTR");
19//!
20//! for unit in UnitOfMeasure::ALL {
21//!     println!("{} — {}", unit.code(), unit.name());
22//! }
23//! ```
24
25#![forbid(unsafe_code)]
26#![warn(missing_docs, clippy::pedantic)]
27#![allow(clippy::too_many_lines, clippy::match_same_arms)]
28
29cefact_units_macros::cefact_units!("rec20.xlsx");
30
31#[cfg(test)]
32mod tests {
33    use crate::{UnitCode, UnitOfMeasure};
34
35    #[test]
36    fn basic_lookup() {
37        let kg = UnitOfMeasure::from_code("KGM").unwrap();
38        assert_eq!(kg.name(), "kilogram");
39        assert_eq!(kg.symbol(), Some("kg"));
40    }
41
42    #[test]
43    fn from_str_parses() {
44        let parsed: UnitOfMeasure = "MTR".parse().unwrap();
45        assert_eq!(parsed.code(), "MTR");
46    }
47
48    #[test]
49    fn unknown_code_fails() {
50        assert!(UnitOfMeasure::from_code("INVALID").is_none());
51        assert!("INVALID".parse::<UnitOfMeasure>().is_err());
52    }
53
54    #[test]
55    fn unit_code_roundtrip() {
56        let code: UnitCode = "KGM".parse().unwrap();
57        assert_eq!(code.as_str(), "KGM");
58        let unit = UnitOfMeasure::from_unit_code(code);
59        assert_eq!(unit.unit_code(), code);
60    }
61
62    #[cfg(feature = "case-insensitive")]
63    #[test]
64    fn case_insensitive_lookup() {
65        let kg = UnitOfMeasure::from_code_ignore_case("kgm").unwrap();
66        assert_eq!(kg.code(), "KGM");
67
68        let parsed: UnitOfMeasure = "mtr".parse().unwrap();
69        assert_eq!(parsed.code(), "MTR");
70    }
71
72    #[cfg(feature = "serde")]
73    #[test]
74    fn serde_roundtrip_for_unit_of_measure() {
75        let unit = UnitOfMeasure::from_code("KGM").unwrap();
76        let encoded = serde_json::to_string(&unit).unwrap();
77        assert_eq!(encoded, "\"KGM\"");
78
79        let decoded: UnitOfMeasure = serde_json::from_str(&encoded).unwrap();
80        assert_eq!(decoded, unit);
81    }
82
83    #[cfg(feature = "serde")]
84    #[test]
85    fn serde_roundtrip_for_unit_code() {
86        let code: UnitCode = "MTR".parse().unwrap();
87        let encoded = serde_json::to_string(&code).unwrap();
88        assert_eq!(encoded, "\"MTR\"");
89
90        let decoded: UnitCode = serde_json::from_str(&encoded).unwrap();
91        assert_eq!(decoded, code);
92    }
93}