mirror of
https://github.com/Start9Labs/patch-db.git
synced 2026-03-26 02:11:54 +00:00
destructure
This commit is contained in:
@@ -131,14 +131,19 @@ struct Fns {
|
||||
impl_fns: TokenStream,
|
||||
impl_ref_fns: TokenStream,
|
||||
impl_mut_fns: TokenStream,
|
||||
impl_mut_destructure: TokenStream,
|
||||
}
|
||||
|
||||
fn impl_fns(model_ty: &Type, children: &[ChildInfo]) -> Fns {
|
||||
fn impl_fns(model_ty: &Type, children: &[ChildInfo], name: &Ident) -> Fns {
|
||||
let mut parts_args = TokenStream::new();
|
||||
let mut parts_assignments = TokenStream::new();
|
||||
let mut impl_fns = TokenStream::new();
|
||||
let mut impl_ref_fns = TokenStream::new();
|
||||
let mut impl_mut_fns = TokenStream::new();
|
||||
let mut destructure_members = TokenStream::new();
|
||||
let mut init_destructure_members = TokenStream::new();
|
||||
let mut mkdestructure_members = TokenStream::new();
|
||||
let mut destructure_member_idents = TokenStream::new();
|
||||
for ChildInfo {
|
||||
vis,
|
||||
name,
|
||||
@@ -210,6 +215,7 @@ fn impl_fns(model_ty: &Type, children: &[ChildInfo]) -> Fns {
|
||||
} else {
|
||||
quote! { v }
|
||||
};
|
||||
|
||||
let child_model_ty = replace_self(model_ty.clone(), &ty);
|
||||
parts_args.extend(quote_spanned! { name.span() =>
|
||||
#name: #child_model_ty,
|
||||
@@ -235,7 +241,33 @@ fn impl_fns(model_ty: &Type, children: &[ChildInfo]) -> Fns {
|
||||
self.transmute_mut(|v| #accessor_mut)
|
||||
}
|
||||
});
|
||||
if let Some(accessor) = accessor {
|
||||
destructure_members.extend(quote_spanned! { name.span() =>
|
||||
#vis #name: &'a mut #child_model_ty,
|
||||
});
|
||||
init_destructure_members.extend(quote_spanned! { name.span() =>
|
||||
{
|
||||
#[allow(unused_imports)]
|
||||
use patch_db::value::index::Index;
|
||||
#accessor.index_or_insert(self.as_value_mut())
|
||||
}
|
||||
});
|
||||
mkdestructure_members.extend(quote_spanned! { name.span() =>
|
||||
let #name = <#child_model_ty>::value_as_mut(__patch_db__destructure_map.remove(#accessor).unwrap());
|
||||
});
|
||||
destructure_member_idents.extend(quote_spanned! { name.span() => #name, });
|
||||
}
|
||||
}
|
||||
|
||||
let mod_name = Ident::new(&format!("__patch_db__destructure_{name}"), name.span());
|
||||
let explicit_model_ty = replace_self(
|
||||
model_ty.clone(),
|
||||
&Type::Path(TypePath {
|
||||
qself: None,
|
||||
path: name.clone().into(),
|
||||
}),
|
||||
);
|
||||
|
||||
Fns {
|
||||
from_parts: quote! {
|
||||
pub fn from_parts(#parts_args) -> Self {
|
||||
@@ -249,6 +281,28 @@ fn impl_fns(model_ty: &Type, children: &[ChildInfo]) -> Fns {
|
||||
impl_fns,
|
||||
impl_ref_fns,
|
||||
impl_mut_fns,
|
||||
impl_mut_destructure: quote! {
|
||||
#[allow(non_snake_case)]
|
||||
mod #mod_name {
|
||||
use super::*;
|
||||
pub struct DestructuredMut<'a> {
|
||||
__patch_db__destructure_phantom: std::marker::PhantomData<&'a ()>,
|
||||
#destructure_members
|
||||
}
|
||||
impl patch_db::DestructureMut for #explicit_model_ty {
|
||||
type Destructured<'a> = DestructuredMut<'a>;
|
||||
fn destructure_mut<'a>(&'a mut self) -> Self::Destructured<'a> {
|
||||
use patch_db::ModelExt;
|
||||
let mut __patch_db__destructure_map: std::collections::BTreeMap<_, _> = self.children_mut().into_iter().collect();
|
||||
#mkdestructure_members
|
||||
DestructuredMut {
|
||||
__patch_db__destructure_phantom: std::marker::PhantomData,
|
||||
#destructure_member_idents
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,7 +403,8 @@ fn build_model_struct(base: &DeriveInput, ast: &DataStruct) -> TokenStream {
|
||||
impl_fns,
|
||||
impl_ref_fns,
|
||||
impl_mut_fns,
|
||||
} = impl_fns(&model_ty, &children);
|
||||
impl_mut_destructure,
|
||||
} = impl_fns(&model_ty, &children, name);
|
||||
quote! {
|
||||
impl patch_db::HasModel for #name {
|
||||
type Model = #model_ty;
|
||||
@@ -360,6 +415,7 @@ fn build_model_struct(base: &DeriveInput, ast: &DataStruct) -> TokenStream {
|
||||
#impl_ref_fns
|
||||
#impl_mut_fns
|
||||
}
|
||||
#impl_mut_destructure
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ mod subscriber;
|
||||
mod test;
|
||||
|
||||
pub use imbl_value::Value;
|
||||
pub use model::{HasModel, Model, ModelExt};
|
||||
pub use model::{DestructureMut, HasModel, Model, ModelExt};
|
||||
pub use patch::{DiffPatch, Dump, Revision};
|
||||
pub use patch_db_macro::HasModel;
|
||||
pub use store::{MutateResult, PatchDb, Store, TypedPatchDb};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use imbl_value::Value;
|
||||
use imbl_value::{InternedString, Value};
|
||||
|
||||
pub trait HasModel: Sized {
|
||||
type Model: Model<Self>;
|
||||
@@ -78,9 +78,24 @@ pub trait ModelExt<T>: Model<T> {
|
||||
) -> &'a mut Self::Model<U> {
|
||||
Self::Model::<U>::value_as_mut(f(<Self as sealed::ModelMarker>::as_value_mut(self)))
|
||||
}
|
||||
fn children_mut<'a>(
|
||||
&'a mut self,
|
||||
) -> impl IntoIterator<Item = (&'a InternedString, &'a mut Value)> + Send + Sync {
|
||||
ModelExt::<T>::as_value_mut(self)
|
||||
.as_object_mut()
|
||||
.into_iter()
|
||||
.flat_map(|o| o.iter_mut().map(|(k, v)| (&*k, v)))
|
||||
}
|
||||
}
|
||||
impl<T, M: Model<T>> ModelExt<T> for M {}
|
||||
|
||||
pub trait DestructureMut {
|
||||
type Destructured<'a>
|
||||
where
|
||||
Self: 'a;
|
||||
fn destructure_mut<'a>(&'a mut self) -> Self::Destructured<'a>;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::marker::PhantomData;
|
||||
|
||||
Reference in New Issue
Block a user