dbstruct-derive 0.4.0

Build a typed database by defining a struct
Documentation
mod accessor;
mod new_method;
mod struct_def;

pub use accessor::Accessor;
pub use new_method::NewMethod;
pub use struct_def::Struct;
use syn::parse_quote;

use crate::model::backend::{Backend, ExtraBound};
use crate::model::Model;

pub struct Ir {
    pub definition: Struct,
    pub new: NewMethod,
    pub accessors: Vec<Accessor>,
    pub bounds: Option<syn::WhereClause>,
}

fn bound_to_ir(bound: &ExtraBound) -> syn::TraitBound {
    match bound {
        ExtraBound::Atomic => parse_quote!(dbstruct::traits::data_store::Atomic),
        ExtraBound::Ordered => parse_quote!(dbstruct::traits::data_store::Ordered),
    }
}

fn bounds_from(model: &Model) -> Option<syn::WhereClause> {
    match &model.backend {
        Backend::Trait { bounds } => {
            let bounds = bounds.iter().map(bound_to_ir);
            parse_quote!(where DS: dbstruct::DataStore + std::clone::Clone + #(#bounds),*)
        }
        _ => None,
    }
}

fn backend_type(backend: &Backend) -> syn::Type {
    match backend {
        Backend::Sled => parse_quote!(::dbstruct::sled::Tree),
        Backend::HashMap => parse_quote!(::dbstruct::stores::HashMap),
        Backend::BTreeMap => parse_quote!(::dbstruct::stores::BTreeMap),
        Backend::Trait { .. } => parse_quote!(DS),
        #[cfg(test)]
        Backend::Test => unreachable!("Test backend is not supported for codegen"),
    }
}

impl Ir {
    pub fn from(model: Model) -> Self {
        let definition = Struct::from(&model);
        let new = NewMethod::from(&model, &definition);
        let bounds = bounds_from(&model);
        let backend_ty = backend_type(&model.backend);
        let accessors = model
            .fields
            .into_iter()
            .map(|f| Accessor::from(f, backend_ty.clone()))
            .collect();

        Self {
            definition,
            new,
            accessors,
            bounds,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn ir_gen_does_not_crash() {
        let _ir = Ir::from(Model::mock_u8field());
    }
}