From 0813d531f157f87e479bb9a1416d57a7fa4feb3b Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Sat, 10 Dec 2022 12:50:15 -0600 Subject: [PATCH] add some utilities around AnyValueRc --- packages/core/src/lib.rs | 2 +- packages/core/src/nodes.rs | 49 ++++++++++++++++++++++++++++---- packages/native-core/src/node.rs | 4 +-- packages/tui/src/lib.rs | 4 +-- packages/tui/src/query.rs | 2 +- 5 files changed, 49 insertions(+), 12 deletions(-) diff --git a/packages/core/src/lib.rs b/packages/core/src/lib.rs index 0de74c911..fd8a934f6 100644 --- a/packages/core/src/lib.rs +++ b/packages/core/src/lib.rs @@ -70,7 +70,7 @@ pub(crate) mod innerlude { } pub use crate::innerlude::{ - fc_to_builder, AnyValueBox, Attribute, AttributeValue, Component, DynamicNode, Element, + fc_to_builder, AnyValueRc, Attribute, AttributeValue, Component, DynamicNode, Element, ElementId, Event, Fragment, IntoAttributeValue, IntoDynNode, LazyNodes, Mutation, Mutations, Properties, RenderReturn, Scope, ScopeId, ScopeState, Scoped, SuspenseContext, TaskId, Template, TemplateAttribute, TemplateNode, VComponent, VNode, VText, VirtualDom, diff --git a/packages/core/src/nodes.rs b/packages/core/src/nodes.rs index c776da967..62b88ac83 100644 --- a/packages/core/src/nodes.rs +++ b/packages/core/src/nodes.rs @@ -338,7 +338,7 @@ pub enum AttributeValue<'a> { Listener(ListenerCb<'a>), /// An arbitrary value that implements PartialEq and is static - Any(AnyValueBox), + Any(AnyValueRc), /// A "none" value, resulting in the removal of an attribute from the dom None, @@ -375,10 +375,47 @@ impl<'de, 'a> serde::Deserialize<'de> for ListenerCb<'a> { /// A boxed value that implements PartialEq and Any #[derive(Clone)] -pub struct AnyValueBox(pub Rc); +pub struct AnyValueRc(pub Rc); + +impl PartialEq for AnyValueRc { + fn eq(&self, other: &Self) -> bool { + self.0.any_cmp(other.0.as_ref()) + } +} + +impl AnyValueRc { + /// Returns a reference to the inner value without checking the type. + pub fn downcast_ref_unchecked(&self) -> &T { + unsafe { &*(self.0.as_ref() as *const dyn AnyValue as *const T) } + } + + /// Returns a reference to the inner value. + pub fn downcast_ref(&self) -> Option<&T> { + if self.0.our_typeid() == TypeId::of::() { + Some(self.downcast_ref_unchecked()) + } else { + None + } + } + + /// Checks if the inner value is of type `T`. + pub fn is(&self) -> bool { + self.0.our_typeid() == TypeId::of::() + } +} + +#[test] +fn test_any_value_rc() { + let a = AnyValueRc(Rc::new(1i32)); + assert!(a.is::()); + assert!(!a.is::()); + assert_eq!(a.downcast_ref::(), Some(&1i32)); + assert_eq!(a.downcast_ref::(), None); + assert_eq!(a.downcast_ref_unchecked::(), &1i32); +} #[cfg(feature = "serialize")] -impl serde::Serialize for AnyValueBox { +impl serde::Serialize for AnyValueRc { fn serialize(&self, _: S) -> Result where S: serde::Serializer, @@ -388,7 +425,7 @@ impl serde::Serialize for AnyValueBox { } #[cfg(feature = "serialize")] -impl<'de> serde::Deserialize<'de> for AnyValueBox { +impl<'de> serde::Deserialize<'de> for AnyValueRc { fn deserialize(_: D) -> Result where D: serde::Deserializer<'de>, @@ -419,7 +456,7 @@ impl<'a> PartialEq for AttributeValue<'a> { (Self::Int(l0), Self::Int(r0)) => l0 == r0, (Self::Bool(l0), Self::Bool(r0)) => l0 == r0, (Self::Listener(_), Self::Listener(_)) => true, - (Self::Any(l0), Self::Any(r0)) => l0.0.any_cmp(r0.0.as_ref()), + (Self::Any(l0), Self::Any(r0)) => l0 == r0, _ => false, } } @@ -642,7 +679,7 @@ impl<'a> IntoAttributeValue<'a> for Arguments<'_> { } } -impl<'a> IntoAttributeValue<'a> for AnyValueBox { +impl<'a> IntoAttributeValue<'a> for AnyValueRc { fn into_value(self, _: &'a Bump) -> AttributeValue<'a> { AttributeValue::Any(self) } diff --git a/packages/native-core/src/node.rs b/packages/native-core/src/node.rs index 7220e0fab..6ee7d7184 100644 --- a/packages/native-core/src/node.rs +++ b/packages/native-core/src/node.rs @@ -1,5 +1,5 @@ use crate::{state::State, tree::NodeId}; -use dioxus_core::{AnyValueBox, AttributeValue, ElementId}; +use dioxus_core::{AnyValueRc, AttributeValue, ElementId}; use rustc_hash::{FxHashMap, FxHashSet}; use std::fmt::Debug; @@ -79,7 +79,7 @@ pub enum OwnedAttributeValue { Float(f64), Int(i64), Bool(bool), - Any(AnyValueBox), + Any(AnyValueRc), None, } diff --git a/packages/tui/src/lib.rs b/packages/tui/src/lib.rs index 38638f7c5..e60988a24 100644 --- a/packages/tui/src/lib.rs +++ b/packages/tui/src/lib.rs @@ -185,9 +185,9 @@ fn render_vdom( let rdom = rdom.borrow(); let mut taffy = taffy.lock().expect("taffy lock poisoned"); // size is guaranteed to not change when rendering - resize(frame.size(), &mut *taffy, &rdom); + resize(frame.size(), &mut taffy, &rdom); let root = &rdom[NodeId(0)]; - render::render_vnode(frame, &*taffy, &rdom, root, cfg, Point::ZERO); + render::render_vnode(frame, &taffy, &rdom, root, cfg, Point::ZERO); })?; } else { let rdom = rdom.borrow(); diff --git a/packages/tui/src/query.rs b/packages/tui/src/query.rs index 64da87650..c052ad9ea 100644 --- a/packages/tui/src/query.rs +++ b/packages/tui/src/query.rs @@ -89,7 +89,7 @@ impl<'a> ElementRef<'a> { .ok(); layout.map(|layout| Layout { order: layout.order, - size: layout.size.map(|v| layout_to_screen_space(v)), + size: layout.size.map(layout_to_screen_space), location: Point { x: layout_to_screen_space(layout.location.x), y: layout_to_screen_space(layout.location.y),