dioxus/packages/core/src/any_props.rs

66 lines
1.8 KiB
Rust
Raw Normal View History

2022-11-04 00:34:42 +00:00
use std::marker::PhantomData;
use crate::{
2022-11-04 03:56:31 +00:00
factory::{ComponentReturn, RenderReturn},
2022-11-09 03:39:37 +00:00
innerlude::Scoped,
scopes::{Scope, ScopeState},
2022-11-03 08:38:18 +00:00
Element,
};
2022-11-03 09:11:04 +00:00
pub trait AnyProps<'a> {
fn as_ptr(&self) -> *const ();
2022-11-04 03:56:31 +00:00
fn render(&'a self, bump: &'a ScopeState) -> RenderReturn<'a>;
unsafe fn memoize(&self, other: &dyn AnyProps) -> bool;
}
2022-11-04 00:34:42 +00:00
pub(crate) struct VComponentProps<'a, P, A, F = Element<'a>>
where
2022-11-04 03:56:31 +00:00
F: ComponentReturn<'a, A>,
2022-11-04 00:34:42 +00:00
{
pub render_fn: fn(Scope<'a, P>) -> F,
pub memo: unsafe fn(&P, &P) -> bool,
2022-11-09 18:58:11 +00:00
pub props: P,
2022-11-04 00:34:42 +00:00
pub _marker: PhantomData<A>,
}
2022-11-04 03:56:31 +00:00
impl<'a, P, A, F: ComponentReturn<'a, A>> VComponentProps<'a, P, A, F> {
pub(crate) fn new(
2022-11-04 00:34:42 +00:00
render_fn: fn(Scope<'a, P>) -> F,
memo: unsafe fn(&P, &P) -> bool,
2022-11-09 18:58:11 +00:00
props: P,
) -> Self {
Self {
2022-11-03 09:37:41 +00:00
render_fn,
memo,
props,
2022-11-04 00:34:42 +00:00
_marker: PhantomData,
}
}
}
2022-11-04 03:56:31 +00:00
impl<'a, P, A, F: ComponentReturn<'a, A>> AnyProps<'a> for VComponentProps<'a, P, A, F> {
fn as_ptr(&self) -> *const () {
&self.props as *const _ as *const ()
}
// Safety:
// this will downcast the other ptr as our swallowed type!
// you *must* make this check *before* calling this method
// if your functions are not the same, then you will downcast a pointer into a different type (UB)
unsafe fn memoize(&self, other: &dyn AnyProps) -> bool {
let real_other: &P = &*(other.as_ptr() as *const _ as *const P);
let real_us: &P = &*(self.as_ptr() as *const _ as *const P);
(self.memo)(real_us, real_other)
}
2022-11-09 18:58:11 +00:00
fn render(&'a self, cx: &'a ScopeState) -> RenderReturn<'a> {
2022-11-09 03:39:37 +00:00
let scope = cx.bump().alloc(Scoped {
2022-11-09 18:58:11 +00:00
props: &self.props,
2022-11-04 03:56:31 +00:00
scope: cx,
2022-11-09 03:39:37 +00:00
});
// Call the render function directly
2022-11-04 03:56:31 +00:00
(self.render_fn)(scope).as_return(cx)
}
}