From a977524c6c82dab8485d6d229bf1bd6f84619cde Mon Sep 17 00:00:00 2001 From: alvskar <68168078+alvskar@users.noreply.github.com> Date: Tue, 25 Aug 2026 10:23:41 +0200 Subject: [PATCH] feat: seserialize EngineeringUnits from symbolic name --- crates/bacnet-types/src/enums/units.rs | 65 ++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/crates/bacnet-types/src/enums/units.rs b/crates/bacnet-types/src/enums/units.rs index 12619800..bd616a11 100644 --- a/crates/bacnet-types/src/enums/units.rs +++ b/crates/bacnet-types/src/enums/units.rs @@ -2,6 +2,12 @@ // EngineeringUnits (Clause 21) — large enum, grouped by category // =========================================================================== +#[cfg(all(feature = "serde", not(feature = "std")))] +use alloc::string::String; + +#[cfg(feature = "serde")] +use serde::Deserialize; + bacnet_enum! { /// BACnet engineering units (Clause 21). /// @@ -302,3 +308,62 @@ bacnet_enum! { const SPECIFIC_GRAVITY = 47821; const EUROPEAN_BREWING_CONVENTION = 47822; } + +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for EngineeringUnits { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let string: String = Deserialize::deserialize(deserializer)?; + string.parse().map_err(serde::de::Error::custom) + } +} + +#[cfg(all(test, feature = "serde"))] +mod serde_tests { + use super::EngineeringUnits; + + fn parse(input: &str) -> EngineeringUnits { + serde_json::from_str(&format!("\"{input}\"")).expect("deserializes") + } + + #[test] + fn accepts_every_supported_case_style() { + for input in [ + "degreescelsius", + "DEGREESCELSIUS", + "DegreesCelsius", + "degreesCelsius", + "degrees_celsius", + "DEGREES_CELSIUS", + "degrees-celsius", + "DEGREES-CELSIUS", + ] { + assert_eq!( + parse(input), + EngineeringUnits::DEGREES_CELSIUS, + "input: {input}" + ); + } + } + + #[test] + fn covers_the_full_standard_range() { + assert_eq!(parse("square_meters"), EngineeringUnits::SQUARE_METERS); + assert_eq!( + parse("european-brewing-convention"), + EngineeringUnits::EUROPEAN_BREWING_CONVENTION + ); + } + + #[test] + fn rejects_unknown_names() { + assert!(serde_json::from_str::("\"not-a-unit\"").is_err()); + } + + #[test] + fn rejects_non_string_input() { + assert!(serde_json::from_str::("126").is_err()); + } +}