use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Epidemiology {
pub global_prevalence: Option<f64>,
pub us_prevalence: Option<f64>,
pub annual_incidence: Option<f64>,
pub demographics: Demographics,
pub trend: Trend,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Demographics {
pub median_age_onset: Option<u8>,
pub sex_ratio: Option<String>,
pub risk_factors: Vec<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Trend {
Increasing,
Stable,
Decreasing,
}
impl std::fmt::Display for Trend {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Increasing => f.write_str("Increasing"),
Self::Stable => f.write_str("Stable"),
Self::Decreasing => f.write_str("Decreasing"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn trend_display() {
assert_eq!(Trend::Increasing.to_string(), "Increasing");
assert_eq!(Trend::Stable.to_string(), "Stable");
assert_eq!(Trend::Decreasing.to_string(), "Decreasing");
}
#[test]
fn epidemiology_round_trip_serde() {
let epi = Epidemiology {
global_prevalence: Some(10.0),
us_prevalence: Some(11.3),
annual_incidence: None,
demographics: Demographics {
median_age_onset: Some(55),
sex_ratio: Some("1.1:1 M:F".to_string()),
risk_factors: vec!["obesity".to_string(), "sedentary lifestyle".to_string()],
},
trend: Trend::Increasing,
};
let json = serde_json::to_string(&epi).expect("serialise");
let parsed: Epidemiology = serde_json::from_str(&json).expect("deserialise");
assert_eq!(epi, parsed);
}
#[test]
fn optional_fields_accept_none() {
let epi = Epidemiology {
global_prevalence: None,
us_prevalence: None,
annual_incidence: None,
demographics: Demographics {
median_age_onset: None,
sex_ratio: None,
risk_factors: vec![],
},
trend: Trend::Stable,
};
let json = serde_json::to_string(&epi).expect("serialise");
assert!(json.contains("\"global_prevalence\":null"));
}
}