use std::fmt;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum SeasonalAdjustment {
SeasonallyAdjusted,
NotSeasonallyAdjusted,
SeasonallyAdjustedAnnualRate,
Other(String),
}
impl SeasonalAdjustment {
fn from_label(label: &str) -> Self {
match label {
"Seasonally Adjusted" => Self::SeasonallyAdjusted,
"Not Seasonally Adjusted" => Self::NotSeasonallyAdjusted,
"Seasonally Adjusted Annual Rate" => Self::SeasonallyAdjustedAnnualRate,
other => Self::Other(other.to_owned()),
}
}
pub fn label(&self) -> &str {
match self {
Self::SeasonallyAdjusted => "Seasonally Adjusted",
Self::NotSeasonallyAdjusted => "Not Seasonally Adjusted",
Self::SeasonallyAdjustedAnnualRate => "Seasonally Adjusted Annual Rate",
Self::Other(label) => label,
}
}
pub fn query_code(&self) -> &str {
match self {
Self::SeasonallyAdjusted => "SA",
Self::NotSeasonallyAdjusted => "NSA",
Self::SeasonallyAdjustedAnnualRate => "SAAR",
Self::Other(label) => label,
}
}
}
impl fmt::Display for SeasonalAdjustment {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.label())
}
}
impl<'de> Deserialize<'de> for SeasonalAdjustment {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let label = String::deserialize(deserializer)?;
Ok(Self::from_label(&label))
}
}
impl Serialize for SeasonalAdjustment {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(self.label())
}
}
#[cfg(feature = "schemars")]
impl schemars::JsonSchema for SeasonalAdjustment {
fn schema_name() -> std::borrow::Cow<'static, str> {
"SeasonalAdjustment".into()
}
fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
<String as schemars::JsonSchema>::json_schema(generator)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn known_labels_map_to_variants() {
assert_eq!(
serde_json::from_str::<SeasonalAdjustment>("\"Not Seasonally Adjusted\"").unwrap(),
SeasonalAdjustment::NotSeasonallyAdjusted
);
assert_eq!(
serde_json::from_str::<SeasonalAdjustment>("\"Seasonally Adjusted Annual Rate\"")
.unwrap(),
SeasonalAdjustment::SeasonallyAdjustedAnnualRate
);
}
#[test]
fn unknown_label_is_preserved_verbatim() {
assert_eq!(
serde_json::from_str::<SeasonalAdjustment>("\"Smoothed\"").unwrap(),
SeasonalAdjustment::Other("Smoothed".to_owned())
);
}
#[test]
fn serializes_to_its_label() {
assert_eq!(
serde_json::to_string(&SeasonalAdjustment::SeasonallyAdjustedAnnualRate).unwrap(),
"\"Seasonally Adjusted Annual Rate\""
);
}
#[test]
fn query_codes_match_geofred() {
assert_eq!(SeasonalAdjustment::SeasonallyAdjusted.query_code(), "SA");
assert_eq!(
SeasonalAdjustment::NotSeasonallyAdjusted.query_code(),
"NSA"
);
assert_eq!(
SeasonalAdjustment::SeasonallyAdjustedAnnualRate.query_code(),
"SAAR"
);
}
}