use chrono::{DateTime, Utc};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
impl Serialize for ObjectId {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.0.to_hex())
}
}
impl<'de> Deserialize<'de> for ObjectId {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
bson::oid::ObjectId::parse_str(&s)
.map(ObjectId)
.map_err(serde::de::Error::custom)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ObjectId(bson::oid::ObjectId);
impl ObjectId {
pub fn new() -> Self {
Self(bson::oid::ObjectId::new())
}
pub fn parse(s: &str) -> Result<Self, bson::oid::Error> {
Ok(Self(bson::oid::ObjectId::parse_str(s)?))
}
pub fn to_string(&self) -> String {
self.0.to_hex()
}
pub fn inner(&self) -> &bson::oid::ObjectId {
&self.0
}
}
impl Default for ObjectId {
fn default() -> Self {
Self::new()
}
}
impl From<bson::oid::ObjectId> for ObjectId {
fn from(id: bson::oid::ObjectId) -> Self {
Self(id)
}
}
impl From<ObjectId> for bson::oid::ObjectId {
fn from(id: ObjectId) -> Self {
id.0
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BaseMongoFields {
#[serde(rename = "_id")]
pub id: ObjectId,
#[serde(rename = "createTime")]
pub create_time: DateTime<Utc>,
#[serde(rename = "updateTime")]
pub update_time: DateTime<Utc>,
}
impl BaseMongoFields {
pub fn new() -> Self {
let now = Utc::now();
Self {
id: ObjectId::new(),
create_time: now,
update_time: now,
}
}
pub fn touch(&mut self) {
self.update_time = Utc::now();
}
}
impl Default for BaseMongoFields {
fn default() -> Self {
Self::new()
}
}
pub trait MongoEntity: Send + Sync {
fn collection_name() -> &'static str;
fn id(&self) -> &ObjectId;
fn create_time(&self) -> &DateTime<Utc>;
fn update_time(&self) -> &DateTime<Utc>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_object_id() {
let id = ObjectId::new();
let id_str = id.to_string();
assert_eq!(id_str.len(), 24);
let parsed = ObjectId::parse(&id_str).unwrap();
assert_eq!(id, parsed);
}
#[test]
fn test_base_mongo_fields() {
let mut fields = BaseMongoFields::new();
let old_update_time = fields.update_time;
std::thread::sleep(std::time::Duration::from_millis(10));
fields.touch();
assert!(fields.update_time > old_update_time);
}
}