component.rs 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. use crate::{
  2. innerlude::{ComponentPtr, Element, Scope, ScopeId, ScopeState},
  3. Component,
  4. };
  5. use std::cell::{Cell, RefCell};
  6. /// Virtual Components for custom user-defined components
  7. /// Only supports the functional syntax
  8. pub struct VComponent<'src> {
  9. /// The key of the component to be used during keyed diffing.
  10. pub key: Option<&'src str>,
  11. /// The ID of the component.
  12. /// Will not be assigned until after the component has been initialized.
  13. pub scope: Cell<Option<ScopeId>>,
  14. /// An indication if the component is static (can be memozied)
  15. pub can_memoize: bool,
  16. /// The function pointer to the component's render function.
  17. pub user_fc: ComponentPtr,
  18. /// The actual name of the component.
  19. pub fn_name: &'static str,
  20. /// The props of the component.
  21. pub props: RefCell<Option<Box<dyn AnyProps + 'src>>>,
  22. }
  23. pub(crate) struct VComponentProps<P> {
  24. pub render_fn: Component<P>,
  25. pub memo: unsafe fn(&P, &P) -> bool,
  26. pub props: P,
  27. }
  28. pub trait AnyProps {
  29. fn as_ptr(&self) -> *const ();
  30. fn render<'a>(&'a self, bump: &'a ScopeState) -> Element<'a>;
  31. unsafe fn memoize(&self, other: &dyn AnyProps) -> bool;
  32. }
  33. impl<P> AnyProps for VComponentProps<P> {
  34. fn as_ptr(&self) -> *const () {
  35. &self.props as *const _ as *const ()
  36. }
  37. // Safety:
  38. // this will downcast the other ptr as our swallowed type!
  39. // you *must* make this check *before* calling this method
  40. // if your functions are not the same, then you will downcast a pointer into a different type (UB)
  41. unsafe fn memoize(&self, other: &dyn AnyProps) -> bool {
  42. let real_other: &P = &*(other.as_ptr() as *const _ as *const P);
  43. let real_us: &P = &*(self.as_ptr() as *const _ as *const P);
  44. (self.memo)(real_us, real_other)
  45. }
  46. fn render<'a>(&'a self, scope: &'a ScopeState) -> Element<'a> {
  47. let props = unsafe { std::mem::transmute::<&P, &P>(&self.props) };
  48. (self.render_fn)(Scope { scope, props })
  49. }
  50. }