use std::{ borrow::{Borrow, Cow}, collections::HashSet, str::FromStr, }; use chrono::{NaiveDateTime, TimeDelta}; use sqlx::{ encode::IsNull, prelude::FromRow, sqlite::{SqliteArgumentValue, SqliteTypeInfo, SqliteValue}, Decode, Sqlite, Type, TypeInfo, Value, ValueRef, }; #[derive(FromRow)] pub struct Task { id: Option, pub name: String, pub cron: Option, pub archived: bool, pub description: Option, pub categories: HashSet, } impl Task { pub fn new( name: String, cron: Option, description: Option, categories: Option>, ) -> Self { Self { id: None, name, cron, archived: false, description, categories: categories.unwrap_or_else(|| HashSet::new()), } } pub fn id(&self) -> Option { self.id } pub fn add_id(mut self, id: i64) -> Self { self.id = Some(id); self } } pub struct Schedule(cron::Schedule); impl sqlx::Encode<'_, Sqlite> for Schedule { fn encode_by_ref( &self, buf: &mut ::ArgumentBuffer<'_>, ) -> Result { let schedule = &self.0; let schedule = schedule.to_string(); buf.push(SqliteArgumentValue::Text(Cow::Owned(schedule))); Ok(IsNull::No) } } impl sqlx::Decode<'_, Sqlite> for Schedule { fn decode( value: ::ValueRef<'_>, ) -> Result { let schedule = Decode::::decode(value)?; let schedule = cron::Schedule::from_str(schedule)?; Ok(Self(schedule)) } } impl Type for Schedule { fn type_info() -> ::TypeInfo { <&str as Type>::type_info() } } #[repr(transparent)] pub struct Category(String); impl Category { pub fn new(category: String) -> Self { Self(category) } } pub struct Log(NaiveDateTime); impl Log { pub fn new(datetime: NaiveDateTime) -> Self { Self(datetime) } } pub struct Reminder(TimeDelta); impl Reminder { pub fn new(time_delta: TimeDelta) -> Self { Self(time_delta) } }