2022-11-02 01:42:29 +00:00
|
|
|
use futures_util::Future;
|
|
|
|
|
2022-10-20 16:56:09 +00:00
|
|
|
use crate::{
|
2022-11-02 01:42:29 +00:00
|
|
|
component::{Component, ComponentFn, Dummy, IntoComponent},
|
2022-10-28 04:58:47 +00:00
|
|
|
scopes::{Scope, ScopeState},
|
2022-11-03 08:38:18 +00:00
|
|
|
Element,
|
2022-10-20 16:56:09 +00:00
|
|
|
};
|
|
|
|
|
2022-10-28 04:58:47 +00:00
|
|
|
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-10-20 16:56:09 +00:00
|
|
|
}
|
|
|
|
|
2022-11-02 01:42:29 +00:00
|
|
|
pub(crate) struct VComponentProps<P, F: Future<Output = ()> = Dummy> {
|
|
|
|
pub render_fn: ComponentFn<P, F>,
|
2022-10-20 16:56:09 +00:00
|
|
|
pub memo: unsafe fn(&P, &P) -> bool,
|
2022-11-02 01:42:29 +00:00
|
|
|
pub props: *const P,
|
2022-10-20 16:56:09 +00:00
|
|
|
}
|
|
|
|
|
2022-10-28 04:58:47 +00:00
|
|
|
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(),
|
2022-10-28 04:58:47 +00:00
|
|
|
memo: <() as PartialEq>::eq,
|
2022-11-02 01:42:29 +00:00
|
|
|
props: std::ptr::null_mut(),
|
2022-10-28 04:58:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
2022-10-28 04:58:47 +00:00
|
|
|
) -> Self {
|
|
|
|
Self {
|
2022-11-02 01:42:29 +00:00
|
|
|
render_fn: render_fn.into_component(),
|
2022-10-28 04:58:47 +00:00
|
|
|
memo,
|
|
|
|
props,
|
|
|
|
}
|
|
|
|
}
|
2022-10-20 16:56:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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> {
|
2022-10-28 04:58:47 +00:00
|
|
|
// 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,
|
|
|
|
};
|
2022-10-28 04:58:47 +00:00
|
|
|
|
|
|
|
// 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!(),
|
|
|
|
}
|
2022-10-20 16:56:09 +00:00
|
|
|
}
|
|
|
|
}
|