diff options
| author | Joe Carstairs <me@joeac.net> | 2024-12-12 08:28:04 +0000 |
|---|---|---|
| committer | Joe Carstairs <me@joeac.net> | 2024-12-12 08:28:04 +0000 |
| commit | 54894f9de9bad4fecb2a116d59a03cdd003f84c0 (patch) | |
| tree | 6ce5517cecf23d4e93d7a381a374e1fa6c810cee /schist_models/src/budget_period_unit.rs | |
| parent | 8a30bcbdf9264d235bf93da3df8e170cfde53d02 (diff) | |
Moves rust workspace to root
Diffstat (limited to 'schist_models/src/budget_period_unit.rs')
| -rw-r--r-- | schist_models/src/budget_period_unit.rs | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/schist_models/src/budget_period_unit.rs b/schist_models/src/budget_period_unit.rs new file mode 100644 index 0000000..77d8641 --- /dev/null +++ b/schist_models/src/budget_period_unit.rs @@ -0,0 +1,112 @@ +use core::fmt; +use std::str::FromStr; + +use anyhow::{Result, bail}; +use diesel::{backend::Backend, deserialize::{self, FromSql, FromSqlRow}, expression::AsExpression, serialize::{self, ToSql}, sql_types::Text, sqlite::Sqlite}; +use serde::{Deserialize, Serialize}; + +#[derive( + Eq, + PartialEq, + Serialize, + Deserialize, + Clone, + Debug, + AsExpression, + FromSqlRow, +)] +#[diesel(sql_type=Text)] +pub enum BudgetPeriodUnit { + Day, + Month, + Year, +} + +impl fmt::Display for BudgetPeriodUnit { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + BudgetPeriodUnit::Day => "DAY".fmt(f), + BudgetPeriodUnit::Month => "MONTH".fmt(f), + BudgetPeriodUnit::Year => "YEAR".fmt(f), + } + } +} + +impl FromStr for BudgetPeriodUnit { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result<Self> { + match s { + "DAY" => Ok(BudgetPeriodUnit::Day), + "MONTH" => Ok(BudgetPeriodUnit::Month), + "YEAR" => Ok(BudgetPeriodUnit::Year), + _ => bail!("\"{}\" is not a valid budget period unit. Valid values are: DAY, MONTH, YEAR", s), + } + } +} + +impl ToSql<Text, Sqlite> for BudgetPeriodUnit { + fn to_sql<'b>( + &'b self, + out: &mut diesel::serialize::Output<'b, '_, Sqlite>, + ) -> serialize::Result { + out.set_value(self.to_string()); + Ok(serialize::IsNull::No) + } +} + +impl FromSql<Text, Sqlite> for BudgetPeriodUnit { + fn from_sql(bytes: <Sqlite as Backend>::RawValue<'_>) -> deserialize::Result<BudgetPeriodUnit> { + let str = <String as FromSql<Text, Sqlite>>::from_sql(bytes)?; + Ok(str.parse()?) + } +} + +#[cfg(test)] +mod test { + use anyhow::Result; + + use super::BudgetPeriodUnit; + + #[test] + fn display_when_day_then_day() { + assert_eq!("DAY", format!("{}", BudgetPeriodUnit::Day)); + } + + #[test] + fn display_when_month_then_month() { + assert_eq!("MONTH", format!("{}", BudgetPeriodUnit::Month)); + } + + #[test] + fn display_when_year_then_year() { + assert_eq!("YEAR", format!("{}", BudgetPeriodUnit::Year)); + } + + #[test] + fn from_str_when_day_then_day() { + let result: Result<BudgetPeriodUnit> = "DAY".parse(); + assert!(result.is_ok()); + assert_eq!(BudgetPeriodUnit::Day, result.unwrap()); + } + + #[test] + fn from_str_when_month_then_month() { + let result: Result<BudgetPeriodUnit> = "MONTH".parse(); + assert!(result.is_ok()); + assert_eq!(BudgetPeriodUnit::Month, result.unwrap()); + } + + #[test] + fn from_str_when_year_then_year() { + let result: Result<BudgetPeriodUnit> = "YEAR".parse(); + assert!(result.is_ok()); + assert_eq!(BudgetPeriodUnit::Year, result.unwrap()); + } + + #[test] + fn from_str_when_sentence_case_day_then_err() { + let result: Result<BudgetPeriodUnit> = "Day".parse(); + assert!(result.is_err()); + } +} |
