use chrono::NaiveDate;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
pub struct RulesetId(pub &'static str);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub struct RulesetVersion(pub &'static str);
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Effectivity {
InForce {
from: NaiveDate,
until: Option<NaiveDate>,
},
Pending {
empowerment: &'static str,
adoption_deadline: Option<NaiveDate>,
},
}
impl Effectivity {
#[must_use]
pub const fn open(from: NaiveDate) -> Self {
Self::InForce { from, until: None }
}
#[must_use]
pub const fn closed(from: NaiveDate, until: NaiveDate) -> Self {
Self::InForce {
from,
until: Some(until),
}
}
#[must_use]
pub const fn pending(empowerment: &'static str, adoption_deadline: Option<NaiveDate>) -> Self {
Self::Pending {
empowerment,
adoption_deadline,
}
}
#[must_use]
pub fn is_active_on(&self, date: NaiveDate) -> bool {
match self {
Self::InForce { from, until } => date >= *from && until.is_none_or(|u| date <= u),
Self::Pending { .. } => false,
}
}
pub fn ensure_active_on(
&self,
id: &RulesetId,
date: NaiveDate,
) -> Result<(), crate::error::CalcError> {
match self {
Self::Pending { empowerment, .. } => {
Err(crate::error::CalcError::RulesetUndetermined {
id: id.0.to_owned(),
empowerment: (*empowerment).to_owned(),
})
}
Self::InForce { from, until } => {
if date < *from {
return Err(crate::error::CalcError::RulesetNotYetEffective {
id: id.0.to_owned(),
from: from.to_string(),
});
}
if let Some(until) = until
&& date > *until
{
return Err(crate::error::CalcError::RulesetExpired {
id: id.0.to_owned(),
until: until.to_string(),
});
}
Ok(())
}
}
}
}
#[derive(Debug, Clone, Serialize)]
pub struct RegulatoryBasis {
pub regulation: &'static str,
pub article: &'static str,
pub standard: Option<&'static str>,
pub technical_study: Option<&'static str>,
pub source_url: Option<&'static str>,
pub superseded_by: Option<&'static str>,
}
pub trait Ruleset {
fn id(&self) -> &RulesetId;
fn version(&self) -> &RulesetVersion;
fn effectivity(&self) -> &Effectivity;
fn regulatory_basis(&self) -> &RegulatoryBasis;
}