mongod 0.3.6

An abstraction layer on mongodb
Documentation
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<u32>,
}

impl Collection for User {
    const COLLECTION: &'static str = "users";

    fn from_document(document: Document) -> Result<Self, Error> {
        let mut document = document;
        let mut name: Option<String> = None;
        let mut age: Option<Option<u32>> = 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::<Bson>::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<Document, Error> {
        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<UserField> for User {}

pub enum UserField {
    Name,
    Age,
}

impl Field for UserField {}

impl From<UserField> 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<Comparator<String>>,
    pub age: Option<Comparator<Option<u32>>>,
}

impl Filter for UserFilter {
    fn new() -> Self {
        Self::default()
    }

    fn into_document(self) -> Result<Document, Error> {
        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<UserFilter> 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<String>,
    pub age: Option<Option<u32>>,
}

impl Update for UserUpdate {
    fn new() -> Self {
        UserUpdate::default()
    }
    fn into_document(self) -> Result<Document, Error> {
        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<UserUpdate> for User {
    fn update() -> UserUpdate {
        UserUpdate::default()
    }
    fn into_update(self) -> UserUpdate {
        UserUpdate {
            name: Some(self.name),
            age: Some(self.age),
        }
    }
}