From e313c40d246ac7545a1907621841090664bf61ae Mon Sep 17 00:00:00 2001 From: cel 🌸 Date: Thu, 5 Jun 2025 03:50:36 +0100 Subject: feat: database functions --- src/task.rs | 110 +++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 64 insertions(+), 46 deletions(-) (limited to 'src/task.rs') diff --git a/src/task.rs b/src/task.rs index 59aa502..ce2e7e6 100644 --- a/src/task.rs +++ b/src/task.rs @@ -1,25 +1,23 @@ use std::{ - borrow::{Borrow, Cow}, collections::HashSet, + ops::{Deref, DerefMut}, str::FromStr, }; -use chrono::{NaiveDateTime, TimeDelta}; -use sqlx::{ - encode::IsNull, - prelude::FromRow, - sqlite::{SqliteArgumentValue, SqliteTypeInfo, SqliteValue}, - Decode, Sqlite, Type, TypeInfo, Value, ValueRef, +use chrono::{Local, NaiveDateTime, TimeDelta}; +use rusqlite::{ + types::{FromSql, FromSqlError, ToSqlOutput, Value}, + ToSql, }; +use uuid::Uuid; -#[derive(FromRow)] +#[derive(PartialEq, Eq, Clone, Debug)] pub struct Task { - id: Option, - pub name: String, - pub cron: Option, - pub archived: bool, - pub description: Option, - pub categories: HashSet, + pub(crate) name: String, + pub(crate) cron: Option, + pub(crate) archived: bool, + pub(crate) description: Option, + pub(crate) categories: HashSet, } impl Task { @@ -27,10 +25,9 @@ impl Task { name: String, cron: Option, description: Option, - categories: Option>, + categories: Option>, ) -> Self { Self { - id: None, name, cron, archived: false, @@ -38,50 +35,57 @@ impl Task { categories: categories.unwrap_or_else(|| HashSet::new()), } } +} - pub fn id(&self) -> Option { - self.id - } +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct Schedule(cron::Schedule); - pub fn add_id(mut self, id: i64) -> Self { - self.id = Some(id); - self +impl FromSql for Schedule { + fn column_result(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult { + let schedule = value.as_str()?; + let schedule = + cron::Schedule::from_str(schedule).map_err(|e| FromSqlError::Other(Box::new(e)))?; + Ok(Self(schedule)) } } -pub struct Schedule(cron::Schedule); +impl ToSql for Schedule { + fn to_sql(&self) -> rusqlite::Result> { + Ok(rusqlite::types::ToSqlOutput::Owned( + rusqlite::types::Value::Text(self.0.to_string()), + )) + } +} -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))); +#[repr(transparent)] +#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Hash)] +pub struct Category(String); - Ok(IsNull::No) +impl ToSql for Category { + fn to_sql(&self) -> rusqlite::Result> { + Ok(ToSqlOutput::Owned(Value::Text(self.0.clone()))) } } -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 FromSql for Category { + fn column_result(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult { + Ok(Self(value.as_str()?.to_string())) } } -impl Type for Schedule { - fn type_info() -> ::TypeInfo { - <&str as Type>::type_info() +impl Deref for Category { + type Target = String; + + fn deref(&self) -> &Self::Target { + &self.0 } } -#[repr(transparent)] -pub struct Category(String); +impl DerefMut for Category { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} impl Category { pub fn new(category: String) -> Self { @@ -89,11 +93,25 @@ impl Category { } } -pub struct Log(NaiveDateTime); +#[derive(Debug, Clone, Copy)] +pub struct Log { + pub(crate) id: Uuid, + pub(crate) timestamp: NaiveDateTime, +} impl Log { pub fn new(datetime: NaiveDateTime) -> Self { - Self(datetime) + Self { + id: Uuid::new_v4(), + timestamp: datetime, + } + } + + pub fn new_now() -> Self { + Self { + id: Uuid::new_v4(), + timestamp: Local::now().naive_local(), + } } } -- cgit