1#![forbid(unsafe_code)]
15#![doc(
16 html_logo_url = "https://raw.githubusercontent.com/welworx/dimvexa/main/docs/brand/icon-256.png",
17 html_favicon_url = "https://raw.githubusercontent.com/welworx/dimvexa/main/docs/brand/icon-32.png"
18)]
19
20use dimvexa_core::{AmbiguousDef, Error, Exactness, Kind, PrefixMode, Registry, Shape, UnitDef};
21
22#[allow(
24 clippy::unreadable_literal,
25 clippy::too_many_lines,
26 clippy::unicode_not_nfc,
27 missing_docs
28)]
29mod generated {
30 use super::{AmbiguousDef, Exactness, Kind, PrefixMode, Shape, UnitDef};
31 include!(concat!(env!("OUT_DIR"), "/units_generated.rs"));
32}
33
34pub use generated::{AMBIGUOUS, DATA_HASH, DATA_VERSION, PACKS, UNITS};
35
36pub fn registry() -> Result<Registry, Error> {
43 Registry::from_defs(UNITS, AMBIGUOUS)
44}
45
46#[must_use]
48pub fn data_version() -> String {
49 format!("v{DATA_VERSION}+{DATA_HASH}")
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 #[test]
57 fn table_loads_and_is_reasonably_sized() {
58 let reg = registry().unwrap();
59 assert!(reg.len() >= 50, "{}", reg.len());
60 assert_eq!(reg.len(), UNITS.len());
61 assert!(DATA_HASH.starts_with("fnv1a64:"));
62 assert!(PACKS.contains(&"base") && PACKS.contains(&"common"));
63 }
64
65 #[test]
66 fn every_ambiguous_symbol_is_rejected_with_candidates() {
67 let reg = registry().unwrap();
68 for a in AMBIGUOUS {
69 let err = reg.parse(a.symbol).unwrap_err();
70 assert_eq!(err.code(), "ambiguous_symbol", "{}", a.symbol);
71 assert_eq!(err.candidates().len(), a.candidates.len() + a.planned.len());
72 for c in a.candidates {
73 assert!(
74 reg.parse(c).is_ok(),
75 "candidate {c} of {} must resolve",
76 a.symbol
77 );
78 }
79 }
80 for sym in ["ton", "gal", "oz", "pt", "cal", "BTU", "mile", "ppm", "hp"] {
81 assert!(AMBIGUOUS.iter().any(|a| a.symbol == sym), "{sym}");
82 }
83 }
84}