use serde::{Serialize, Deserialize, Deserializer}; use std::fmt; use rand::{thread_rng, Rng}; use chrono::prelude::{DateTime, Utc, NaiveDate}; /// ID #[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Eq, Hash)] pub struct Id(pub u64); impl Into<String> for Id { fn into(self) -> String { format!("{:x}", self.0) } } impl fmt::Display for Id { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.0) } } pub fn generate_id() -> Id { Id(thread_rng().gen()) } /// https://serde.rs/field-attrs.html pub fn deserialize_datetime<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error> where D: Deserializer<'de>, { let s = String::deserialize(deserializer)?; DateTime::parse_from_rfc3339(&s) .map_err(serde::de::Error::custom) .map(|dt| dt.with_timezone(&Utc)) } pub fn deserialize_date<'de, D>(deserializer: D) -> Result<NaiveDate, D::Error> where D: Deserializer<'de>, { let s = String::deserialize(deserializer)?; NaiveDate::parse_from_str(&s, "%Y-%m-%d") .map_err(serde::de::Error::custom) }