From 6419b6357c492d033d2a70839fc8b8843b641310 Mon Sep 17 00:00:00 2001 From: ElnuDev Date: Sun, 10 Jul 2022 14:11:45 -0700 Subject: [PATCH] Refactor comment serialization/deserialization --- Cargo.lock | 1 + Cargo.toml | 2 +- src/comment.rs | 63 ++++++++++++++++--------------------------------- src/database.rs | 16 ++++--------- src/main.rs | 6 ++--- 5 files changed, 30 insertions(+), 58 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index be6ede7..e1fa8d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -324,6 +324,7 @@ dependencies = [ "libc", "num-integer", "num-traits", + "serde", "time 0.1.44", "winapi", ] diff --git a/Cargo.toml b/Cargo.toml index c16dc99..6ec2ea4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,4 +13,4 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" validator = { version = "0.15.0", features = ["derive"] } md5 = "0.7.0" -chrono = "0.4.19" +chrono = { version = "0.4.19", features = ["serde"] } diff --git a/src/comment.rs b/src/comment.rs index f35bf04..65404f9 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -1,54 +1,31 @@ -use chrono::NaiveDateTime; -use serde::{Deserialize, Serialize}; +use chrono::serde::ts_seconds_option; +use chrono::{DateTime, Utc}; +use serde::{Deserialize, Serialize, Serializer}; use validator::Validate; // Master comment type that is stored in database +#[derive(Serialize, Deserialize, Validate)] pub struct Comment { - pub author: Option, // None/null is Anonymous - pub email: Option, - pub text: String, - pub timestamp: Option, -} - -impl Comment { - pub fn send(&self) -> CommentSend { - CommentSend { - author: self.author.clone(), - gravatar: match self.email.clone() { - Some(email) => Some(format!("{:x}", md5::compute(email.to_lowercase()))), - None => None, - }, - text: self.text.clone(), - timestamp: self.timestamp.unwrap().timestamp(), - } - } -} - -// Comment type for API responses -#[derive(Serialize)] -pub struct CommentSend { - pub author: Option, - pub gravatar: Option, - pub text: String, - pub timestamp: i64, -} - -// Comment type received containing new comment data -#[derive(Deserialize, Validate)] -pub struct CommentReceive { - pub author: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub author: Option, // None is Anonymous + #[serde(rename(serialize = "gravatar"))] + #[serde(serialize_with = "serialize_gravatar")] #[validate(email)] + #[serde(skip_serializing_if = "Option::is_none")] pub email: Option, + #[validate(length(min = 1))] pub text: String, + #[serde(default)] + #[serde(with = "ts_seconds_option")] + #[serde(skip_serializing_if = "Option::is_none")] + pub timestamp: Option>, } -impl CommentReceive { - pub fn to_master(&self) -> Comment { - Comment { - author: self.author.clone(), - email: self.email.clone(), - text: self.text.clone(), - timestamp: None, - } +fn serialize_gravatar(email: &Option, s: S) -> Result +where S: Serializer, +{ + match email { + Some(email) => s.serialize_some(&format!("{:x}", md5::compute(email.to_lowercase()))), + None => s.serialize_none(), } } diff --git a/src/database.rs b/src/database.rs index 3f89699..8adcc99 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1,5 +1,4 @@ -use crate::comment::{Comment, CommentSend}; -use chrono::NaiveDateTime; +use crate::Comment; use rusqlite::{params, Connection, Result}; pub struct Database { @@ -25,20 +24,15 @@ impl Database { Ok(Self { conn }) } - pub fn get_send_comments(&self) -> Result> { + pub fn get_comments(&self) -> Result> { self.conn .prepare("SELECT author, email, text, timestamp FROM comment ORDER BY timestamp DESC")? .query_map([], |row| { - let timestamp: NaiveDateTime = row.get(3)?; - let timestamp = timestamp.timestamp(); - Ok(CommentSend { + Ok(Comment { author: row.get(0)?, - gravatar: match row.get::>(1)? { - Some(email) => Some(format!("{:x}", md5::compute(email.to_lowercase()))), - None => None, - }, + email: row.get(1)?, text: row.get(2)?, - timestamp: timestamp, + timestamp: row.get(3)?, }) })? .collect() diff --git a/src/main.rs b/src/main.rs index 5f92d64..2b8eb9f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,7 +19,7 @@ async fn get_comments(data: web::Data) -> impl Responder { Ok(db) => db, Err(_) => return HttpResponse::InternalServerError().into(), }; - HttpResponse::Ok().json(&db.get_send_comments().unwrap()) + HttpResponse::Ok().json(&db.get_comments().unwrap()) } #[post("/")] @@ -30,14 +30,14 @@ async fn post_comment(data: web::Data, bytes: web::Bytes) -> impl Resp Ok(db) => db, Err(_) => return HttpResponse::InternalServerError(), }; - let comment: CommentReceive = match serde_json::from_str(&text) { + let comment: Comment = match serde_json::from_str(&text) { Ok(comment) => comment, Err(_) => return HttpResponse::BadRequest(), }; if comment.validate().is_err() { return HttpResponse::BadRequest(); } - db.create_comment(&comment.to_master()).unwrap(); + db.create_comment(&comment).unwrap(); HttpResponse::Ok() } Err(_) => HttpResponse::BadRequest().into(),