use crate::{DynamicValues, Template, VNode};
use dioxus_core_template::{
TEMPLATE_STORAGE_DYNAMIC_CAP, TEMPLATE_STORAGE_OPS_CAP, TEMPLATE_STORAGE_STRING_CAP,
TemplateRawTree, TemplateStorage,
};
use std::marker::PhantomData;
pub trait ViewTemplate {
const TEMPLATE_TREE: &'static TemplateRawTree;
}
struct StaticViewTemplate<
V,
const OPS_CAP: usize,
const STRING_CAP: usize,
const DYNAMIC_CAP: usize,
>(PhantomData<fn() -> V>);
impl<V: ViewTemplate, const OPS_CAP: usize, const STRING_CAP: usize, const DYNAMIC_CAP: usize>
StaticViewTemplate<V, OPS_CAP, STRING_CAP, DYNAMIC_CAP>
{
const TEMPLATE: &'static Template =
&TemplateStorage::<OPS_CAP, STRING_CAP, DYNAMIC_CAP>::build_from_tree(V::TEMPLATE_TREE)
.as_template();
}
impl ViewTemplate for () {
const TEMPLATE_TREE: &'static TemplateRawTree = &TemplateRawTree::Empty;
}
pub trait View: ViewTemplate + Sized {
#[inline]
fn push(self, _: &mut DynamicValues) {}
}
pub struct KeyedView<V> {
key: Option<String>,
view: V,
}
impl<V: ViewTemplate> ViewTemplate for KeyedView<V> {
const TEMPLATE_TREE: &'static TemplateRawTree = V::TEMPLATE_TREE;
}
impl<V: View> View for KeyedView<V> {
#[inline]
fn push(self, dynamic: &mut DynamicValues) {
dynamic.set_key(self.key);
self.view.push(dynamic);
}
}
pub trait ViewKeyExt: View {
fn key(self, key: Option<String>) -> KeyedView<Self>;
}
impl<V: View> ViewKeyExt for V {
#[inline]
fn key(self, key: Option<String>) -> KeyedView<Self> {
KeyedView { key, view: self }
}
}
pub trait ViewExt: View {
fn into_vnode(self) -> VNode;
}
impl<V: View> ViewExt for V {
#[inline]
fn into_vnode(self) -> VNode {
into_vnode_with_template(
self,
StaticViewTemplate::<
V,
TEMPLATE_STORAGE_OPS_CAP,
TEMPLATE_STORAGE_STRING_CAP,
TEMPLATE_STORAGE_DYNAMIC_CAP,
>::TEMPLATE,
)
}
}
#[inline]
fn into_vnode_with_template<V: View>(view: V, template: &Template) -> VNode {
let mut dynamic = DynamicValues::new();
view.push(&mut dynamic);
VNode::new(*template, dynamic)
}
#[cfg(debug_assertions)]
#[doc(hidden)]
pub fn into_vnode_cached<V: View>(view: V, cache: &std::sync::OnceLock<Template>) -> VNode {
let template =
*cache.get_or_init(|| dioxus_core_template::build_runtime_template(V::TEMPLATE_TREE));
into_vnode_with_template(view, &template)
}
pub fn into_vnode_with_capacity<
const OPS_CAP: usize,
const STRING_CAP: usize,
const DYNAMIC_CAP: usize,
V: View,
>(
view: V,
) -> VNode {
into_vnode_with_template(
view,
StaticViewTemplate::<V, OPS_CAP, STRING_CAP, DYNAMIC_CAP>::TEMPLATE,
)
}
impl View for () {}