use std::convert::{TryFrom, TryInto}; use serde::{Deserialize, Serialize}; use mongod::bson::{Bson, Document}; use mongod::ext; use mongod::{AsField, AsFilter, AsUpdate, Collection, Comparator, Error, Field, Filter, Update}; #[derive(Deserialize, Serialize)] pub struct User { pub name: String, pub age: Option, } impl Collection for User { const COLLECTION: &'static str = "users"; fn from_document(document: Document) -> Result { let mut document = document; let mut name: Option = None; let mut age: Option> = None; if let Some(value) = document.remove("name") { name = Some(String::try_from(ext::bson::Bson(value))?); } if let Some(value) = document.remove("age") { let wrap = ext::bson::Bson(value); let opt = match Option::::from(wrap) { Some(v) => Some( ext::bson::Bson(v) .try_into() .map_err(Error::invalid_document)?, ), None => None, }; age = Some(opt) } if name.is_none() { return Err(Error::invalid_document("missing required field `name`")); } if age.is_none() { return Err(Error::invalid_document("missing required field `age`")); } Ok(Self { name: name.expect("could not get name"), age: age.expect("could not get name"), }) } fn into_document(self) -> Result { let mut doc = Document::new(); doc.insert("name", self.name); doc.insert("age", ext::bson::Bson::try_from(self.age)?.0); Ok(doc) } } impl AsField for User {} pub enum UserField { Name, Age, } impl Field for UserField {} impl From for String { fn from(field: UserField) -> String { match field { UserField::Name => "name".to_owned(), UserField::Age => "age".to_owned(), } } } #[derive(Default)] pub struct UserFilter { pub name: Option>, pub age: Option>>, } impl Filter for UserFilter { fn new() -> Self { Self::default() } fn into_document(self) -> Result { let mut doc = Document::new(); if let Some(value) = self.name { doc.insert("name", ext::bson::Bson::try_from(value)?.0); } if let Some(value) = self.age { doc.insert("age", ext::bson::Bson::try_from(value)?.0); } Ok(doc) } } impl AsFilter for User { fn filter() -> UserFilter { UserFilter::default() } fn into_filter(self) -> UserFilter { UserFilter { name: Some(Comparator::Eq(self.name)), age: Some(Comparator::Eq(self.age)), } } } #[derive(Default)] pub struct UserUpdate { pub name: Option, pub age: Option>, } impl Update for UserUpdate { fn new() -> Self { UserUpdate::default() } fn into_document(self) -> Result { let mut doc = Document::new(); if let Some(value) = self.name { doc.insert("name", value); } if let Some(value) = self.age { doc.insert("age", ext::bson::Bson::try_from(value)?.0); } Ok(doc) } } impl AsUpdate for User { fn update() -> UserUpdate { UserUpdate::default() } fn into_update(self) -> UserUpdate { UserUpdate { name: Some(self.name), age: Some(self.age), } } }