dioxus/packages/core/src/any_props.rs

79 lines
2.1 KiB
Rust
Raw Normal View History

use std::cell::Cell;
2022-11-02 01:42:29 +00:00
use futures_util::Future;
use crate::{
2022-11-02 01:42:29 +00:00
component::{Component, ComponentFn, Dummy, IntoComponent},
element::Element,
scopes::{Scope, ScopeState},
};
pub trait AnyProps {
fn as_ptr(&self) -> *const ();
fn render<'a>(&'a self, bump: &'a ScopeState) -> Element<'a>;
unsafe fn memoize(&self, other: &dyn AnyProps) -> bool;
}
2022-11-02 01:42:29 +00:00
pub(crate) struct VComponentProps<P, F: Future<Output = ()> = Dummy> {
pub render_fn: ComponentFn<P, F>,
pub memo: unsafe fn(&P, &P) -> bool,
2022-11-02 01:42:29 +00:00
pub props: *const P,
}
impl VComponentProps<()> {
pub fn new_empty(render_fn: Component<()>) -> Self {
Self {
2022-11-02 01:42:29 +00:00
render_fn: render_fn.into_component(),
memo: <() as PartialEq>::eq,
2022-11-02 01:42:29 +00:00
props: std::ptr::null_mut(),
}
}
}
impl<P> VComponentProps<P> {
pub(crate) fn new(
render_fn: Component<P>,
memo: unsafe fn(&P, &P) -> bool,
2022-11-02 01:42:29 +00:00
props: *const P,
) -> Self {
Self {
2022-11-02 01:42:29 +00:00
render_fn: render_fn.into_component(),
memo,
props,
}
}
}
impl<P> AnyProps for VComponentProps<P> {
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)
}
fn render<'a>(&'a self, scope: &'a ScopeState) -> Element<'a> {
// Make sure the scope ptr is not null
2022-11-02 01:42:29 +00:00
// self.props.state.set(scope);
let scope = Scope {
props: unsafe { &*self.props },
scope,
};
// Call the render function directly
// todo: implement async
2022-11-02 01:42:29 +00:00
match self.render_fn {
ComponentFn::Sync(f) => f(scope),
ComponentFn::Async(_) => todo!(),
}
}
}