summaryrefslogtreecommitdiff
path: root/schist_models/src/budget_period_unit.rs
diff options
context:
space:
mode:
authorJoe Carstairs <me@joeac.net>2024-12-12 08:28:04 +0000
committerJoe Carstairs <me@joeac.net>2024-12-12 08:28:04 +0000
commit54894f9de9bad4fecb2a116d59a03cdd003f84c0 (patch)
tree6ce5517cecf23d4e93d7a381a374e1fa6c810cee /schist_models/src/budget_period_unit.rs
parent8a30bcbdf9264d235bf93da3df8e170cfde53d02 (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.rs112
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());
+ }
+}