Fix attribute value in macro (#577)
* create into AttributeValue trait to allow arbitraty attribute values * allow attributevalue in non-template macro
This commit is contained in:
1 parent
e8c48d46cf
commit
ab10d327ac
4 files changed
+156
-40
No files matched your search
@@ -1,5 +1,6 @@
|
|||||||
use std::fmt::Formatter;
|
use std::fmt::{Arguments, Formatter};
|
||||||
|
|
||||||
|
use bumpalo::Bump;
|
||||||
use dyn_clone::{clone_box, DynClone};
|
use dyn_clone::{clone_box, DynClone};
|
||||||
|
|
||||||
/// Possible values for an attribute
|
/// Possible values for an attribute
|
||||||
@@ -30,6 +31,133 @@ pub enum AttributeValue<'a> {
|
|||||||
Any(ArbitraryAttributeValue<'a>),
|
Any(ArbitraryAttributeValue<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A value that can be converted into an attribute value
|
||||||
|
pub trait IntoAttributeValue<'a> {
|
||||||
|
/// Convert into an attribute value
|
||||||
|
fn into_value(self, bump: &'a Bump) -> AttributeValue<'a>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoAttributeValue<'a> for u32 {
|
||||||
|
fn into_value(self, _: &'a Bump) -> AttributeValue<'a> {
|
||||||
|
AttributeValue::Uint32(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoAttributeValue<'a> for u64 {
|
||||||
|
fn into_value(self, _: &'a Bump) -> AttributeValue<'a> {
|
||||||
|
AttributeValue::Uint64(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoAttributeValue<'a> for i32 {
|
||||||
|
fn into_value(self, _: &'a Bump) -> AttributeValue<'a> {
|
||||||
|
AttributeValue::Int32(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoAttributeValue<'a> for i64 {
|
||||||
|
fn into_value(self, _: &'a Bump) -> AttributeValue<'a> {
|
||||||
|
AttributeValue::Int64(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoAttributeValue<'a> for f32 {
|
||||||
|
fn into_value(self, _: &'a Bump) -> AttributeValue<'a> {
|
||||||
|
AttributeValue::Float32(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoAttributeValue<'a> for f64 {
|
||||||
|
fn into_value(self, _: &'a Bump) -> AttributeValue<'a> {
|
||||||
|
AttributeValue::Float64(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoAttributeValue<'a> for bool {
|
||||||
|
fn into_value(self, _: &'a Bump) -> AttributeValue<'a> {
|
||||||
|
AttributeValue::Bool(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoAttributeValue<'a> for &'a str {
|
||||||
|
fn into_value(self, _: &'a Bump) -> AttributeValue<'a> {
|
||||||
|
AttributeValue::Text(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoAttributeValue<'a> for Arguments<'_> {
|
||||||
|
fn into_value(self, bump: &'a Bump) -> AttributeValue<'a> {
|
||||||
|
use bumpalo::core_alloc::fmt::Write;
|
||||||
|
let mut str_buf = bumpalo::collections::String::new_in(bump);
|
||||||
|
str_buf.write_fmt(self).unwrap();
|
||||||
|
AttributeValue::Text(str_buf.into_bump_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoAttributeValue<'a> for &'a [u8] {
|
||||||
|
fn into_value(self, _: &'a Bump) -> AttributeValue<'a> {
|
||||||
|
AttributeValue::Bytes(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoAttributeValue<'a> for (f32, f32, f32) {
|
||||||
|
fn into_value(self, _: &'a Bump) -> AttributeValue<'a> {
|
||||||
|
AttributeValue::Vec3Float(self.0, self.1, self.2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoAttributeValue<'a> for (i32, i32, i32) {
|
||||||
|
fn into_value(self, _: &'a Bump) -> AttributeValue<'a> {
|
||||||
|
AttributeValue::Vec3Int(self.0, self.1, self.2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoAttributeValue<'a> for (u32, u32, u32) {
|
||||||
|
fn into_value(self, _: &'a Bump) -> AttributeValue<'a> {
|
||||||
|
AttributeValue::Vec3Uint(self.0, self.1, self.2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoAttributeValue<'a> for (f32, f32, f32, f32) {
|
||||||
|
fn into_value(self, _: &'a Bump) -> AttributeValue<'a> {
|
||||||
|
AttributeValue::Vec4Float(self.0, self.1, self.2, self.3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoAttributeValue<'a> for (i32, i32, i32, i32) {
|
||||||
|
fn into_value(self, _: &'a Bump) -> AttributeValue<'a> {
|
||||||
|
AttributeValue::Vec4Int(self.0, self.1, self.2, self.3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoAttributeValue<'a> for (u32, u32, u32, u32) {
|
||||||
|
fn into_value(self, _: &'a Bump) -> AttributeValue<'a> {
|
||||||
|
AttributeValue::Vec4Uint(self.0, self.1, self.2, self.3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> IntoAttributeValue<'a> for &'a T
|
||||||
|
where
|
||||||
|
T: AnyClone + PartialEq,
|
||||||
|
{
|
||||||
|
fn into_value(self, _: &'a Bump) -> AttributeValue<'a> {
|
||||||
|
AttributeValue::Any(ArbitraryAttributeValue {
|
||||||
|
value: self,
|
||||||
|
cmp: |a, b| {
|
||||||
|
if let Some(a) = a.as_any().downcast_ref::<T>() {
|
||||||
|
if let Some(b) = b.as_any().downcast_ref::<T>() {
|
||||||
|
a == b
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// todo
|
// todo
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
impl<'a> AttributeValue<'a> {
|
impl<'a> AttributeValue<'a> {
|
||||||
|
|||||||
+14
-12
@@ -69,13 +69,14 @@ pub(crate) mod innerlude {
|
|||||||
pub use crate::innerlude::{
|
pub use crate::innerlude::{
|
||||||
AnyEvent, ArbitraryAttributeValue, Attribute, AttributeDiscription, AttributeValue,
|
AnyEvent, ArbitraryAttributeValue, Attribute, AttributeDiscription, AttributeValue,
|
||||||
CodeLocation, Component, DioxusElement, DomEdit, DynamicNodeMapping, Element, ElementId,
|
CodeLocation, Component, DioxusElement, DomEdit, DynamicNodeMapping, Element, ElementId,
|
||||||
ElementIdIterator, EventHandler, EventPriority, GlobalNodeId, IntoVNode, LazyNodes, Listener,
|
ElementIdIterator, EventHandler, EventPriority, GlobalNodeId, IntoAttributeValue, IntoVNode,
|
||||||
Mutations, NodeFactory, OwnedAttributeValue, Properties, RendererTemplateId, SchedulerMsg,
|
LazyNodes, Listener, Mutations, NodeFactory, OwnedAttributeValue, Properties,
|
||||||
Scope, ScopeId, ScopeState, StaticCodeLocation, StaticDynamicNodeMapping, StaticTemplateNode,
|
RendererTemplateId, SchedulerMsg, Scope, ScopeId, ScopeState, StaticCodeLocation,
|
||||||
StaticTemplateNodes, TaskId, Template, TemplateAttribute, TemplateAttributeValue,
|
StaticDynamicNodeMapping, StaticTemplateNode, StaticTemplateNodes, TaskId, Template,
|
||||||
TemplateContext, TemplateElement, TemplateId, TemplateNode, TemplateNodeId, TemplateNodeType,
|
TemplateAttribute, TemplateAttributeValue, TemplateContext, TemplateElement, TemplateId,
|
||||||
TemplateValue, TextTemplate, TextTemplateSegment, UiEvent, UserEvent, VComponent, VElement,
|
TemplateNode, TemplateNodeId, TemplateNodeType, TemplateValue, TextTemplate,
|
||||||
VFragment, VNode, VPlaceholder, VText, VirtualDom, JS_MAX_INT,
|
TextTemplateSegment, UiEvent, UserEvent, VComponent, VElement, VFragment, VNode, VPlaceholder,
|
||||||
|
VText, VirtualDom, JS_MAX_INT,
|
||||||
};
|
};
|
||||||
#[cfg(any(feature = "hot-reload", debug_assertions))]
|
#[cfg(any(feature = "hot-reload", debug_assertions))]
|
||||||
pub use crate::innerlude::{
|
pub use crate::innerlude::{
|
||||||
@@ -92,11 +93,12 @@ pub mod prelude {
|
|||||||
pub use crate::innerlude::OwnedTemplate;
|
pub use crate::innerlude::OwnedTemplate;
|
||||||
pub use crate::innerlude::{
|
pub use crate::innerlude::{
|
||||||
fc_to_builder, AttributeDiscription, AttributeValue, Attributes, CodeLocation, Component,
|
fc_to_builder, AttributeDiscription, AttributeValue, Attributes, CodeLocation, Component,
|
||||||
DioxusElement, Element, EventHandler, Fragment, LazyNodes, LazyStaticVec, NodeFactory,
|
DioxusElement, Element, EventHandler, Fragment, IntoAttributeValue, LazyNodes,
|
||||||
Properties, Scope, ScopeId, ScopeState, StaticAttributeValue, StaticCodeLocation,
|
LazyStaticVec, NodeFactory, Properties, Scope, ScopeId, ScopeState, StaticAttributeValue,
|
||||||
StaticDynamicNodeMapping, StaticTemplate, StaticTemplateNodes, Template, TemplateAttribute,
|
StaticCodeLocation, StaticDynamicNodeMapping, StaticTemplate, StaticTemplateNodes,
|
||||||
TemplateAttributeValue, TemplateContext, TemplateElement, TemplateId, TemplateNode,
|
Template, TemplateAttribute, TemplateAttributeValue, TemplateContext, TemplateElement,
|
||||||
TemplateNodeId, TemplateNodeType, TextTemplate, TextTemplateSegment, VNode, VirtualDom,
|
TemplateId, TemplateNode, TemplateNodeId, TemplateNodeType, TextTemplate,
|
||||||
|
TextTemplateSegment, VNode, VirtualDom,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
dynamic_template_context::TemplateContext,
|
dynamic_template_context::TemplateContext,
|
||||||
innerlude::{
|
innerlude::{
|
||||||
AttributeValue, ComponentPtr, Element, Properties, Scope, ScopeId, ScopeState, Template,
|
AttributeValue, ComponentPtr, Element, IntoAttributeValue, Properties, Scope, ScopeId,
|
||||||
TemplateId,
|
ScopeState, Template, TemplateId,
|
||||||
},
|
},
|
||||||
lazynodes::LazyNodes,
|
lazynodes::LazyNodes,
|
||||||
template::{TemplateNodeId, VTemplateRef},
|
template::{TemplateNodeId, VTemplateRef},
|
||||||
@@ -698,13 +698,12 @@ impl<'a> NodeFactory<'a> {
|
|||||||
pub fn attr_disciption(
|
pub fn attr_disciption(
|
||||||
&self,
|
&self,
|
||||||
discription: AttributeDiscription,
|
discription: AttributeDiscription,
|
||||||
val: Arguments,
|
val: impl IntoAttributeValue<'a>,
|
||||||
) -> Attribute<'a> {
|
) -> Attribute<'a> {
|
||||||
let (value, is_static) = self.raw_text(val);
|
|
||||||
Attribute {
|
Attribute {
|
||||||
attribute: discription,
|
attribute: discription,
|
||||||
is_static,
|
is_static: false,
|
||||||
value: AttributeValue::Text(value),
|
value: val.into_value(self.bump),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -712,19 +711,18 @@ impl<'a> NodeFactory<'a> {
|
|||||||
pub fn attr(
|
pub fn attr(
|
||||||
&self,
|
&self,
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
val: Arguments,
|
val: impl IntoAttributeValue<'a>,
|
||||||
namespace: Option<&'static str>,
|
namespace: Option<&'static str>,
|
||||||
is_volatile: bool,
|
is_volatile: bool,
|
||||||
) -> Attribute<'a> {
|
) -> Attribute<'a> {
|
||||||
let (value, is_static) = self.raw_text(val);
|
|
||||||
Attribute {
|
Attribute {
|
||||||
attribute: AttributeDiscription {
|
attribute: AttributeDiscription {
|
||||||
name,
|
name,
|
||||||
namespace,
|
namespace,
|
||||||
volatile: is_volatile,
|
volatile: is_volatile,
|
||||||
},
|
},
|
||||||
is_static,
|
is_static: false,
|
||||||
value: AttributeValue::Text(value),
|
value: val.into_value(self.bump),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -421,10 +421,7 @@ impl TemplateBuilder {
|
|||||||
element_tag: el.name.clone(),
|
element_tag: el.name.clone(),
|
||||||
name: AttributeName::Ident(name),
|
name: AttributeName::Ident(name),
|
||||||
value: TemplateAttributeValue::Dynamic(
|
value: TemplateAttributeValue::Dynamic(
|
||||||
self.dynamic_context.add_attr(quote!(AttributeValue::Text(
|
self.dynamic_context.add_attr(quote!(#value)),
|
||||||
dioxus::core::exports::bumpalo::format!(in __bump, "{}", #value)
|
|
||||||
.into_bump_str()
|
|
||||||
))),
|
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -443,10 +440,7 @@ impl TemplateBuilder {
|
|||||||
element_tag: el.name.clone(),
|
element_tag: el.name.clone(),
|
||||||
name: AttributeName::Str(name),
|
name: AttributeName::Str(name),
|
||||||
value: TemplateAttributeValue::Dynamic(
|
value: TemplateAttributeValue::Dynamic(
|
||||||
self.dynamic_context.add_attr(quote!(AttributeValue::Text(
|
self.dynamic_context.add_attr(quote!(#value)),
|
||||||
dioxus::core::exports::bumpalo::format!(in __bump, "{}", #value)
|
|
||||||
.into_bump_str()
|
|
||||||
))),
|
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -456,10 +450,7 @@ impl TemplateBuilder {
|
|||||||
element_tag: el.name.clone(),
|
element_tag: el.name.clone(),
|
||||||
name: AttributeName::Ident(name),
|
name: AttributeName::Ident(name),
|
||||||
value: TemplateAttributeValue::Dynamic(
|
value: TemplateAttributeValue::Dynamic(
|
||||||
self.dynamic_context.add_attr(quote!(AttributeValue::Text(
|
self.dynamic_context.add_attr(quote!(#value)),
|
||||||
dioxus::core::exports::bumpalo::format!(in __bump, "{}", #value)
|
|
||||||
.into_bump_str()
|
|
||||||
))),
|
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -468,10 +459,7 @@ impl TemplateBuilder {
|
|||||||
element_tag: el.name.clone(),
|
element_tag: el.name.clone(),
|
||||||
name: AttributeName::Str(name),
|
name: AttributeName::Str(name),
|
||||||
value: TemplateAttributeValue::Dynamic(
|
value: TemplateAttributeValue::Dynamic(
|
||||||
self.dynamic_context.add_attr(quote!(AttributeValue::Text(
|
self.dynamic_context.add_attr(quote!(#value)),
|
||||||
dioxus::core::exports::bumpalo::format!(in __bump, "{}", #value)
|
|
||||||
.into_bump_str()
|
|
||||||
))),
|
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -879,7 +867,7 @@ impl ToTokens for DynamicTemplateContextBuilder {
|
|||||||
TemplateContext {
|
TemplateContext {
|
||||||
nodes: __cx.bump().alloc([#(#nodes),*]),
|
nodes: __cx.bump().alloc([#(#nodes),*]),
|
||||||
text_segments: __cx.bump().alloc([#(&*dioxus::core::exports::bumpalo::format!(in __bump, "{}", #text).into_bump_str()),*]),
|
text_segments: __cx.bump().alloc([#(&*dioxus::core::exports::bumpalo::format!(in __bump, "{}", #text).into_bump_str()),*]),
|
||||||
attributes: __cx.bump().alloc([#(#attributes),*]),
|
attributes: __cx.bump().alloc([#({#attributes}.into_value(__cx.bump())),*]),
|
||||||
listeners: __cx.bump().alloc([#(dioxus_elements::on::#listeners_names(__cx, #listeners_exprs)),*]),
|
listeners: __cx.bump().alloc([#(dioxus_elements::on::#listeners_names(__cx, #listeners_exprs)),*]),
|
||||||
key: #key,
|
key: #key,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user