use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(from = "String", into = "String")]
#[non_exhaustive]
pub enum Regime {
Espr,
BatteryRegulation,
ToySafety,
Detergents,
Cpr,
Ppwr,
Elv,
EcodesignEnergyLabelling,
Other(String),
None,
}
impl Regime {
#[must_use]
pub fn wire_str(&self) -> Option<&'static str> {
Some(match self {
Self::Espr => "espr",
Self::BatteryRegulation => "battery-regulation",
Self::ToySafety => "toy-safety",
Self::Detergents => "detergents",
Self::Cpr => "cpr",
Self::Ppwr => "ppwr",
Self::Elv => "elv",
Self::EcodesignEnergyLabelling => "ecodesign-energy-labelling",
Self::None => "none",
Self::Other(_) => return Option::None,
})
}
}
impl From<String> for Regime {
fn from(s: String) -> Self {
match s.as_str() {
"espr" => Self::Espr,
"battery-regulation" => Self::BatteryRegulation,
"toy-safety" => Self::ToySafety,
"detergents" => Self::Detergents,
"cpr" => Self::Cpr,
"ppwr" => Self::Ppwr,
"elv" => Self::Elv,
"ecodesign-energy-labelling" => Self::EcodesignEnergyLabelling,
"none" => Self::None,
_ => Self::Other(s),
}
}
}
impl From<Regime> for String {
fn from(regime: Regime) -> Self {
match regime {
Regime::Other(s) => s,
modelled => modelled
.wire_str()
.expect("every non-Other variant has a wire string")
.to_owned(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn every_modelled_variant_round_trips_as_a_bare_string() {
for regime in [
Regime::Espr,
Regime::BatteryRegulation,
Regime::ToySafety,
Regime::Detergents,
Regime::Cpr,
Regime::Ppwr,
Regime::Elv,
Regime::EcodesignEnergyLabelling,
Regime::None,
] {
let json = serde_json::to_string(®ime).expect("serialise");
assert!(
json.starts_with('"'),
"{regime:?} must render as a string, got {json}"
);
assert_eq!(
serde_json::from_str::<Regime>(&json).expect("deserialise"),
regime
);
}
}
#[test]
fn an_unmodelled_instrument_is_absorbed_not_rejected() {
let parsed: Regime =
serde_json::from_str("\"circular-economy-act\"").expect("must not fail");
assert_eq!(parsed, Regime::Other("circular-economy-act".to_owned()));
assert_eq!(
serde_json::to_string(&parsed).unwrap(),
"\"circular-economy-act\""
);
}
}