1use std::any::TypeId;
2
3use ratatui_kit_macros::Props;
4
5pub trait Props {}
9
10trait DropRaw {
13 fn drop_raw(&self, raw: *mut ());
14}
15
16struct DropRawImpl<T> {
19 _marker: std::marker::PhantomData<T>,
20}
21
22impl<T> DropRaw for DropRawImpl<T> {
23 fn drop_raw(&self, raw: *mut ()) {
26 unsafe {
27 let _ = Box::from_raw(raw as *mut T);
28 }
29 }
30}
31
32#[doc(hidden)]
38pub struct AnyProps<'a> {
39 raw: *mut (),
40 type_id: TypeId,
41 drop: Option<Box<dyn DropRaw + 'a>>,
42 _marker: std::marker::PhantomData<&'a mut ()>,
43}
44
45impl<'a> AnyProps<'a> {
46 pub(crate) fn owned<T>(props: T, type_id: TypeId) -> Self
49 where
50 T: Props + 'a,
51 {
52 let raw = Box::into_raw(Box::new(props));
54 Self {
55 raw: raw as *mut (),
56 type_id,
57 drop: Some(Box::new(DropRawImpl::<T> {
59 _marker: std::marker::PhantomData,
60 })),
61 _marker: std::marker::PhantomData,
62 }
63 }
64
65 pub(crate) fn borrowed<T: Props>(props: &'a mut T, type_id: TypeId) -> Self {
68 Self {
69 raw: props as *const _ as *mut (),
70 type_id,
71 drop: None, _marker: std::marker::PhantomData,
73 }
74 }
75
76 pub(crate) fn borrow(&mut self) -> AnyProps<'_> {
79 Self {
80 raw: self.raw,
81 type_id: self.type_id,
82 drop: None,
83 _marker: std::marker::PhantomData,
84 }
85 }
86
87 pub(crate) unsafe fn downcast_ref_unchecked<T: Props>(&self, expected_type_id: TypeId) -> &T {
90 debug_assert_eq!(
91 self.type_id, expected_type_id,
92 "AnyProps type mismatch before immutable downcast"
93 );
94 unsafe { &*(self.raw as *const T) }
95 }
96
97 pub(crate) unsafe fn downcast_mut_unchecked<T: Props>(
100 &mut self,
101 expected_type_id: TypeId,
102 ) -> &mut T {
103 debug_assert_eq!(
104 self.type_id, expected_type_id,
105 "AnyProps type mismatch before mutable downcast"
106 );
107 unsafe { &mut *(self.raw as *mut T) }
108 }
109}
110
111impl Drop for AnyProps<'_> {
113 fn drop(&mut self) {
114 if let Some(drop) = self.drop.take() {
116 drop.drop_raw(self.raw);
117 }
118 }
119}
120
121#[derive(Debug, Clone, Default, Props)]
122pub struct NoProps;