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_fns: TokenStream,
|
||||||
impl_ref_fns: TokenStream,
|
impl_ref_fns: TokenStream,
|
||||||
impl_mut_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_args = TokenStream::new();
|
||||||
let mut parts_assignments = TokenStream::new();
|
let mut parts_assignments = TokenStream::new();
|
||||||
let mut impl_fns = TokenStream::new();
|
let mut impl_fns = TokenStream::new();
|
||||||
let mut impl_ref_fns = TokenStream::new();
|
let mut impl_ref_fns = TokenStream::new();
|
||||||
let mut impl_mut_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 {
|
for ChildInfo {
|
||||||
vis,
|
vis,
|
||||||
name,
|
name,
|
||||||
@@ -210,6 +215,7 @@ fn impl_fns(model_ty: &Type, children: &[ChildInfo]) -> Fns {
|
|||||||
} else {
|
} else {
|
||||||
quote! { v }
|
quote! { v }
|
||||||
};
|
};
|
||||||
|
|
||||||
let child_model_ty = replace_self(model_ty.clone(), &ty);
|
let child_model_ty = replace_self(model_ty.clone(), &ty);
|
||||||
parts_args.extend(quote_spanned! { name.span() =>
|
parts_args.extend(quote_spanned! { name.span() =>
|
||||||
#name: #child_model_ty,
|
#name: #child_model_ty,
|
||||||
@@ -235,7 +241,33 @@ fn impl_fns(model_ty: &Type, children: &[ChildInfo]) -> Fns {
|
|||||||
self.transmute_mut(|v| #accessor_mut)
|
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 {
|
Fns {
|
||||||
from_parts: quote! {
|
from_parts: quote! {
|
||||||
pub fn from_parts(#parts_args) -> Self {
|
pub fn from_parts(#parts_args) -> Self {
|
||||||
@@ -249,6 +281,28 @@ fn impl_fns(model_ty: &Type, children: &[ChildInfo]) -> Fns {
|
|||||||
impl_fns,
|
impl_fns,
|
||||||
impl_ref_fns,
|
impl_ref_fns,
|
||||||
impl_mut_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_fns,
|
||||||
impl_ref_fns,
|
impl_ref_fns,
|
||||||
impl_mut_fns,
|
impl_mut_fns,
|
||||||
} = impl_fns(&model_ty, &children);
|
impl_mut_destructure,
|
||||||
|
} = impl_fns(&model_ty, &children, name);
|
||||||
quote! {
|
quote! {
|
||||||
impl patch_db::HasModel for #name {
|
impl patch_db::HasModel for #name {
|
||||||
type Model = #model_ty;
|
type Model = #model_ty;
|
||||||
@@ -360,6 +415,7 @@ fn build_model_struct(base: &DeriveInput, ast: &DataStruct) -> TokenStream {
|
|||||||
#impl_ref_fns
|
#impl_ref_fns
|
||||||
#impl_mut_fns
|
#impl_mut_fns
|
||||||
}
|
}
|
||||||
|
#impl_mut_destructure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ mod subscriber;
|
|||||||
mod test;
|
mod test;
|
||||||
|
|
||||||
pub use imbl_value::Value;
|
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::{DiffPatch, Dump, Revision};
|
||||||
pub use patch_db_macro::HasModel;
|
pub use patch_db_macro::HasModel;
|
||||||
pub use store::{MutateResult, PatchDb, Store, TypedPatchDb};
|
pub use store::{MutateResult, PatchDb, Store, TypedPatchDb};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use imbl_value::Value;
|
use imbl_value::{InternedString, Value};
|
||||||
|
|
||||||
pub trait HasModel: Sized {
|
pub trait HasModel: Sized {
|
||||||
type Model: Model<Self>;
|
type Model: Model<Self>;
|
||||||
@@ -78,9 +78,24 @@ pub trait ModelExt<T>: Model<T> {
|
|||||||
) -> &'a mut Self::Model<U> {
|
) -> &'a mut Self::Model<U> {
|
||||||
Self::Model::<U>::value_as_mut(f(<Self as sealed::ModelMarker>::as_value_mut(self)))
|
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 {}
|
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)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|||||||
Reference in New Issue
Block a user