diff --git a/packages/native-core-macro/src/lib.rs b/packages/native-core-macro/src/lib.rs index 21f28623b..a5d6af001 100644 --- a/packages/native-core-macro/src/lib.rs +++ b/packages/native-core-macro/src/lib.rs @@ -4,7 +4,7 @@ use std::collections::HashSet; use proc_macro::TokenStream; use quote::{format_ident, quote}; -use syn::{parse_macro_input, ItemImpl, Type, TypeTuple, TypePath}; +use syn::{parse_macro_input, ItemImpl, Type, TypePath, TypeTuple}; /// A helper attribute for deriving `State` for a struct. #[proc_macro_attribute] @@ -46,7 +46,8 @@ pub fn partial_derive_state(_: TokenStream, input: TokenStream) -> TokenStream { .expect("NodeDependencies must be defined"); let this_type = &impl_block.self_ty; - let this_type = extract_type_path(this_type).unwrap_or_else(|| panic!("Self must be a type path, found {}", quote!(#this_type))); + let this_type = extract_type_path(this_type) + .unwrap_or_else(|| panic!("Self must be a type path, found {}", quote!(#this_type))); let mut combined_dependencies = HashSet::new(); @@ -56,7 +57,12 @@ pub fn partial_derive_state(_: TokenStream, input: TokenStream) -> TokenStream { Some(tuple) => { let mut parent_dependencies = Vec::new(); for type_ in &tuple.elems { - let mut type_ = extract_type_path(type_).unwrap_or_else(|| panic!("ParentDependencies must be a tuple of type paths, found {}", quote!(#type_))); + let mut type_ = extract_type_path(type_).unwrap_or_else(|| { + panic!( + "ParentDependencies must be a tuple of type paths, found {}", + quote!(#type_) + ) + }); if type_ == self_path { type_ = this_type.clone(); } @@ -65,13 +71,21 @@ pub fn partial_derive_state(_: TokenStream, input: TokenStream) -> TokenStream { } parent_dependencies } - _ => panic!("ParentDependencies must be a tuple, found {}", quote!(#parent_dependencies)), + _ => panic!( + "ParentDependencies must be a tuple, found {}", + quote!(#parent_dependencies) + ), }; let child_dependencies = match extract_tuple(child_dependencies) { Some(tuple) => { let mut child_dependencies = Vec::new(); for type_ in &tuple.elems { - let mut type_ = extract_type_path(type_).unwrap_or_else(|| panic!("ChildDependencies must be a tuple of type paths, found {}", quote!(#type_))); + let mut type_ = extract_type_path(type_).unwrap_or_else(|| { + panic!( + "ChildDependencies must be a tuple of type paths, found {}", + quote!(#type_) + ) + }); if type_ == self_path { type_ = this_type.clone(); } @@ -80,13 +94,21 @@ pub fn partial_derive_state(_: TokenStream, input: TokenStream) -> TokenStream { } child_dependencies } - _ => panic!("ChildDependencies must be a tuple, found {}", quote!(#child_dependencies)), + _ => panic!( + "ChildDependencies must be a tuple, found {}", + quote!(#child_dependencies) + ), }; let node_dependencies = match extract_tuple(node_dependencies) { Some(tuple) => { let mut node_dependencies = Vec::new(); for type_ in &tuple.elems { - let mut type_ = extract_type_path(type_).unwrap_or_else(|| panic!("NodeDependencies must be a tuple of type paths, found {}", quote!(#type_))); + let mut type_ = extract_type_path(type_).unwrap_or_else(|| { + panic!( + "NodeDependencies must be a tuple of type paths, found {}", + quote!(#type_) + ) + }); if type_ == self_path { type_ = this_type.clone(); } @@ -95,7 +117,10 @@ pub fn partial_derive_state(_: TokenStream, input: TokenStream) -> TokenStream { } node_dependencies } - _ => panic!("NodeDependencies must be a tuple, found {}", quote!(#node_dependencies)), + _ => panic!( + "NodeDependencies must be a tuple, found {}", + quote!(#node_dependencies) + ), }; combined_dependencies.insert(this_type.clone()); @@ -146,11 +171,11 @@ pub fn partial_derive_state(_: TokenStream, input: TokenStream) -> TokenStream { .map(|i| { let ident = format_ident!("__data{}", i); if i == this_type_idx { - quote!{mut #ident} + quote! {mut #ident} } else { - quote!{#ident} + quote! {#ident} } - }) + }) .collect(); let node_view = node_dependencies_idxes @@ -174,6 +199,19 @@ pub fn partial_derive_state(_: TokenStream, input: TokenStream) -> TokenStream { } } }; + let deref_node_view = { + if node_dependencies.is_empty() { + quote! { + let node = raw_node; + } + } else { + let indexes = (0..node_dependencies.len()).map(syn::Index::from); + quote! { + let node = unsafe { (#(dioxus_native_core::prelude::DependancyView::new(&*raw_node.#indexes),)*) }; + } + } + }; + let parent_view = parent_dependancies_idxes .iter() .map(|i| format_ident!("__data{}", i)) @@ -198,16 +236,29 @@ pub fn partial_derive_state(_: TokenStream, input: TokenStream) -> TokenStream { } } }; - let child_view = child_dependencies_idxes - .iter() - .map(|i| format_ident!("__data{}", i)) - .collect::>(); -let get_child_view = { - if child_dependencies.is_empty() { - quote! { - let raw_children: Vec<_> = tree.children_ids(id).into_iter().map(|_| ()).collect(); + let deref_parent_view = { + if parent_dependencies.is_empty() { + quote! { + let parent = raw_parent; + } + } else { + let indexes = (0..parent_dependencies.len()).map(syn::Index::from); + quote! { + let parent = unsafe { raw_parent.map(|raw_parent| (#(dioxus_native_core::prelude::DependancyView::new(&*raw_parent.#indexes),)*)) }; + } } - } else { + }; + + let child_view = child_dependencies_idxes + .iter() + .map(|i| format_ident!("__data{}", i)) + .collect::>(); + let get_child_view = { + if child_dependencies.is_empty() { + quote! { + let raw_children: Vec<_> = tree.children_ids(id).into_iter().map(|_| ()).collect(); + } + } else { let temps = (0..child_dependencies.len()) .map(|i| format_ident!("__temp{}", i)) .collect::>(); @@ -222,6 +273,18 @@ let get_child_view = { } } }; + let deref_child_view = { + if child_dependencies.is_empty() { + quote! { + let children = raw_children; + } + } else { + let indexes = (0..child_dependencies.len()).map(syn::Index::from); + quote! { + let children = unsafe { raw_children.iter().map(|raw_children| (#(dioxus_native_core::prelude::DependancyView::new(&*raw_children.#indexes),)*)).collect::>() }; + } + } + }; let trait_generics = trait_ .as_ref() @@ -258,10 +321,10 @@ let get_child_view = { #get_parent_view #get_child_view - let myself: Option<&mut Self> = unsafe { raw_myself.map(|val| std::mem::transmute(val)) }; - let node = unsafe { std::mem::transmute(raw_node) }; - let parent = unsafe { raw_parent.map(|val| std::mem::transmute(val)) }; - let children = unsafe { std::mem::transmute(raw_children) }; + let myself: Option<&mut Self> = unsafe { raw_myself.map(|val| &mut *val) }; + #deref_node_view + #deref_parent_view + #deref_child_view let view = NodeView::new(id, node_data, &node_mask); if let Some(myself) = myself { @@ -296,4 +359,4 @@ fn extract_type_path(ty: &Type) -> Option { Type::Group(group) => extract_type_path(&group.elem), _ => None, } -} \ No newline at end of file +} diff --git a/packages/native-core/src/lib.rs b/packages/native-core/src/lib.rs index 34a2332e9..955e1ba6a 100644 --- a/packages/native-core/src/lib.rs +++ b/packages/native-core/src/lib.rs @@ -29,7 +29,7 @@ pub mod exports { pub mod prelude { pub use crate::node::{ElementNode, FromAnyValue, NodeType, OwnedAttributeView, TextNode}; pub use crate::node_ref::{AttributeMaskBuilder, NodeMaskBuilder, NodeView}; - pub use crate::passes::{AnyState, Dependancy, State}; + pub use crate::passes::{AnyState, Dependancy, DependancyView, State}; pub use crate::real_dom::{NodeImmutable, NodeMut, NodeRef, RealDom}; pub use crate::NodeId; pub use crate::SendAnyMap;