diff options
Diffstat (limited to 'src/model.rs')
| -rw-r--r-- | src/model.rs | 197 |
1 files changed, 196 insertions, 1 deletions
diff --git a/src/model.rs b/src/model.rs index 37a855f..8f0e76f 100644 --- a/src/model.rs +++ b/src/model.rs @@ -347,19 +347,104 @@ impl SubscriptionQuery<'_> { } // TODO +#[derive(Debug, PartialEq)] pub struct Mail { pub from: String, pub recipient: Vec<String>, pub data: String, } +enum MailQuery<'a> { + Insert(&'a Mail), + Next, + Delete(i64), + Count, +} + +impl Query for MailQuery<'_> { + type T = MailResult; + + fn callback(&self, tx: &rusqlite::Transaction) -> Result<QueryResult<Self::T>> { + match self { + MailQuery::Insert(mail) => self.insert_mail(tx, mail), + MailQuery::Next => self.get_next(tx), + MailQuery::Delete(id) => self.delete(tx, *id), + MailQuery::Count => self.count(tx), + } + } +} + +impl MailQuery<'_> { + fn insert_mail( + &self, + tx: &rusqlite::Transaction, + mail: &Mail, + ) -> Result<QueryResult<MailResult>> { + let q = "INSERT INTO queue (from_, recipient, data) VALUES (?, ?, ?)"; + tx.execute( + q, + (&mail.from, mail.recipient.join(","), mail.data.as_bytes()), + )?; + Ok(QueryResult::Empty) + } + + fn get_next(&self, tx: &rusqlite::Transaction) -> Result<QueryResult<MailResult>> { + let q = "SELECT * FROM queue LIMIT 1"; + let ris = tx + .prepare(q)? + .query(())? + .map(|row| { + let mail_data: Vec<u8> = row.get(3).unwrap(); + let recp: String = row.get(2).unwrap(); + let mail = Mail { + from: row.get(1).unwrap(), + recipient: recp + .split(',') + .map(|r| String::from(r)) + .collect::<Vec<String>>(), + data: String::from_utf8(mail_data).unwrap(), + }; + Ok(MailResult::Mail(row.get(0).unwrap(), mail)) + }) + .next()?; + + if ris.is_some() { + Ok(QueryResult::Single(ris.unwrap())) + } else { + Ok(QueryResult::Empty) + } + } + + fn delete(&self, tx: &rusqlite::Transaction, id: i64) -> Result<QueryResult<MailResult>> { + let q = "DELETE FROM queue WHERE id = ?"; + tx.execute(q, [id])?; + Ok(QueryResult::Empty) + } + + fn count(&self, tx: &rusqlite::Transaction) -> Result<QueryResult<MailResult>> { + let q = "SELECT COUNT(*) FROM queue"; + let r = tx + .prepare(q)? + .query(())? + .map(|row| Ok(row.get(0).unwrap())) + .next()? + .unwrap(); + Ok(QueryResult::Single(MailResult::Count(r))) + } +} + +enum MailResult { + Mail(i64, Mail), + Count(i64), +} + #[cfg(test)] mod tests { use anyhow::Result; use crate::{ database::{DB_NAME, Database, QueryResult}, - model::{List, SubscriptionQuery, SubscriptionResult, User}, + model::{List, Mail, MailQuery, SubscriptionQuery, SubscriptionResult, User}, }; fn setup() -> Result<Database> { @@ -778,4 +863,114 @@ mod tests { drop(database); cleanup().expect("failed cleanup"); } + + #[test] + fn mail_insert() { + let mut database = setup().expect("failed setup"); + + let mail = Mail { + from: String::from("mroik@delayed.space"), + recipient: vec![String::from("mroik@poul.org")], + data: String::from("Random data"), + }; + + database + .execute(MailQuery::Insert(&mail)) + .expect("failed insert"); + + let c = database + .execute(MailQuery::Count) + .expect("failed count query"); + match c { + QueryResult::Single(super::MailResult::Count(c)) => assert_eq!(c, 1), + _ => assert!(false), + } + + drop(database); + cleanup().expect("failed cleanup"); + } + + #[test] + fn mail_get_next() { + let mut database = setup().expect("failed setup"); + + let mail = Mail { + from: String::from("mroik@delayed.space"), + recipient: vec![String::from("mroik@poul.org")], + data: String::from("Random data"), + }; + + database + .execute(MailQuery::Insert(&mail)) + .expect("failed insert"); + + let c = database + .execute(MailQuery::Count) + .expect("failed count query"); + match c { + QueryResult::Single(super::MailResult::Count(c)) => assert_eq!(c, 1), + _ => assert!(false), + } + + match database + .execute(MailQuery::Next) + .expect("failed query get next") + { + QueryResult::Single(super::MailResult::Mail(_, m)) => assert_eq!(m, mail), + _ => assert!(false), + } + + drop(database); + cleanup().expect("failed cleanup"); + } + + #[test] + fn mail_delete() { + let mut database = setup().expect("failed setup"); + + let mail = Mail { + from: String::from("mroik@delayed.space"), + recipient: vec![String::from("mroik@poul.org")], + data: String::from("Random data"), + }; + + database + .execute(MailQuery::Insert(&mail)) + .expect("failed insert"); + + let mut c = database + .execute(MailQuery::Count) + .expect("failed count query"); + match c { + QueryResult::Single(super::MailResult::Count(c)) => assert_eq!(c, 1), + _ => assert!(false), + } + + let mut id = None; + match database + .execute(MailQuery::Next) + .expect("failed query get next") + { + QueryResult::Single(super::MailResult::Mail(id_, m)) => { + id = Some(id_); + assert_eq!(m, mail); + } + _ => assert!(false), + } + + database + .execute(MailQuery::Delete(id.unwrap())) + .expect("failed delete"); + + c = database + .execute(MailQuery::Count) + .expect("failed count query"); + match c { + QueryResult::Single(super::MailResult::Count(c)) => assert_eq!(c, 0), + _ => assert!(false), + } + + drop(database); + cleanup().expect("failed cleanup"); + } } |
