use proc_macro::TokenStream;
use quote::quote;
use crate::{model, var};
pub(super) fn impl_model_ext(
m: &model::ModelMeta,
k: &var::ValueMeta,
v: &var::ValueMeta,
) -> TokenStream {
let m_ident = m.ident();
let redb_alias = def_redb_alias(&k, &v);
let model_alias = def_model_alias(&k, &v);
let from_values = def_from_values(&m, &k, &v);
let from_guards = def_from_guards(&m, &k, &v);
let from_key_and_guard = def_from_key_and_guard(&m, &k, &v);
let as_key = def_as_key(&k);
let as_value = def_as_value(&v);
let as_values = def_as_key_and_value(&k, &v);
quote! {
#[automatically_derived]
impl<'a> redb_model::ModelExt<'a> for #m_ident{
#redb_alias
#model_alias
#from_values
#from_guards
#from_key_and_guard
#as_key
#as_value
#as_values
}
}
.into()
}
fn def_redb_alias(k: &var::ValueMeta, v: &var::ValueMeta) -> proc_macro2::TokenStream {
let k_ty = k.redb_ty();
let v_ty = v.redb_ty();
quote! {
type RedbKey = #k_ty;
type RedbValue = #v_ty;
}
}
fn def_model_alias(k: &var::ValueMeta, v: &var::ValueMeta) -> proc_macro2::TokenStream {
let k_ty = k.model_ty();
let v_ty = v.model_ty();
quote! {
type ModelKey = #k_ty;
type ModelValue = #v_ty;
}
}
fn def_from_values(
m: &model::ModelMeta,
k: &var::ValueMeta,
v: &var::ValueMeta,
) -> proc_macro2::TokenStream {
let k_redb_ty = k.redb_ty();
let v_redb_ty = v.redb_ty();
let m_ident = m.ident();
let k_ident_tuple = k.composite_idents();
let v_ident_tuple = v.composite_idents();
let kv = var::ValueMeta::new_merged(k, v);
let kv_idents = kv.idents();
let kv_from_methods = kv.from_methods();
quote! {
fn from_values(
values: (
<#k_redb_ty as redb::Value>::SelfType<'a>,
<#v_redb_ty as redb::Value>::SelfType<'a>
)
) -> Self {
let (#k_ident_tuple, #v_ident_tuple) = (values.0, values.1);
#m_ident { #( #kv_idents: #kv_from_methods), * }
}
}
}
fn def_from_guards(
m: &model::ModelMeta,
k: &var::ValueMeta,
v: &var::ValueMeta,
) -> proc_macro2::TokenStream {
let k_redb_ty = k.redb_ty();
let v_redb_ty = v.redb_ty();
let m_ident = m.ident();
let k_ident_tuple = k.composite_idents();
let v_ident_tuple = v.composite_idents();
let kv = var::ValueMeta::new_merged(k, v);
let kv_idents = kv.idents().collect::<Vec<_>>();
let kv_from_methods = kv.from_methods();
quote! {
fn from_guards(values: (&redb::AccessGuard<'a, #k_redb_ty>, &redb::AccessGuard<'a, #v_redb_ty>)) -> Self {
let (#k_ident_tuple, #v_ident_tuple) = (values.0.value(), values.1.value());
let ( #( #kv_idents ), * ) = ( #( #kv_from_methods ), *);
#m_ident {
#( #kv_idents ), *
}
}
}
}
fn def_from_key_and_guard(
m: &model::ModelMeta,
k: &var::ValueMeta,
v: &var::ValueMeta,
) -> proc_macro2::TokenStream {
let m_ident = m.ident();
let k_redb_ty = k.redb_ty();
let v_redb_ty = v.redb_ty();
let k_ident_tuple = k.composite_idents();
let v_ident_tuple = v.composite_idents();
let kv = var::ValueMeta::new_merged(k, v);
let kv_idents = kv.idents().collect::<Vec<_>>();
let kv_from_methods = kv.from_methods();
quote! {
fn from_key_and_guard(values:
(
<#k_redb_ty as redb::Value>::SelfType<'a>,
&redb::AccessGuard<'a, #v_redb_ty>
)
) -> Self {
let (#k_ident_tuple, #v_ident_tuple) = (values.0, values.1.value());
let ( #( #kv_idents ), * ) = ( #( #kv_from_methods ), *);
#m_ident {
#( #kv_idents ), *
}
}
}
}
fn def_as_key(k: &var::ValueMeta) -> proc_macro2::TokenStream {
let k_redb_ty = k.redb_ty();
let k_idents = k.idents().collect::<Vec<_>>();
let k_into_methods = k.into_methods();
let k_ident_tuple = k.composite_idents();
quote! {
fn as_key (&'a self) -> <#k_redb_ty as redb::Value>::SelfType<'a> {
let ( #( #k_idents ), * ) = ( #( &self.#k_idents ), *);
let ( #( #k_idents ), * ) = ( #( #k_into_methods ), *);
#k_ident_tuple
}
}
}
fn def_as_value(v: &var::ValueMeta) -> proc_macro2::TokenStream {
let v_redb_ty = v.redb_ty();
let v_idents = v.idents().collect::<Vec<_>>();
let v_into_methods = v.into_methods();
let v_ident_tuple = v.composite_idents();
quote! {
fn as_value (&'a self) -> <#v_redb_ty as redb::Value>::SelfType<'a> {
let ( #( #v_idents ), * ) = ( #( &self.#v_idents ), *);
let ( #( #v_idents ), * ) = ( #( #v_into_methods ), *);
#v_ident_tuple
}
}
}
fn def_as_key_and_value(k: &var::ValueMeta, v: &var::ValueMeta) -> proc_macro2::TokenStream {
let k_redb_ty = k.redb_ty();
let v_redb_ty = v.redb_ty();
let k_ident_tuple = k.composite_idents();
let v_ident_tuple = v.composite_idents();
let kv = var::ValueMeta::new_merged(k, v);
let kv_idents = kv.idents().collect::<Vec<_>>();
let kv_into_methods = kv.into_methods();
quote! {
fn as_key_and_value (&'a self) -> (
<#k_redb_ty as redb::Value>::SelfType<'a>,
<#v_redb_ty as redb::Value>::SelfType<'a>
) {
let ( #( #kv_idents ), * ) = ( #( &self.#kv_idents ), *);
let ( #( #kv_idents ), * ) = ( #( #kv_into_methods ), *);
(
#k_ident_tuple,
#v_ident_tuple
)
}
}
}