ratatui_kit/
props.rs

1use ratatui_kit_macros::Props;
2
3/// 组件属性 trait,所有可作为组件 props 的类型都需实现此 trait。
4///
5/// - 需实现 Send + Sync。
6/// - 推荐使用 `#[derive(Props)]` 自动实现。
7///
8/// # Safety
9/// 实现者需保证类型安全和线程安全。
10pub unsafe trait Props: Send + Sync {}
11
12// 用于处理原始指针释放的trait
13// 通过类型擦除实现对未知类型的内存释放
14trait DropRaw {
15    fn drop_raw(&self, raw: *mut ());
16}
17
18// 类型擦除的具体实现
19// 使用PhantomData标记实际类型T
20struct DropRowImpl<T> {
21    _marker: std::marker::PhantomData<T>,
22}
23
24impl<T> DropRaw for DropRowImpl<T> {
25    // 实际执行内存释放的方法
26    // 将原始指针转换为Box后释放
27    fn drop_raw(&self, raw: *mut ()) {
28        unsafe {
29            let _ = Box::from_raw(raw as *mut T);
30        }
31    }
32}
33
34// 类型擦除容器
35// 支持存储任意类型的属性(owned/borrowed)
36// raw: 指向实际数据的原始指针
37// drop: 可选的drop处理函数(对于owned类型)
38// _marker: 生命周期标记
39pub struct AnyProps<'a> {
40    raw: *mut (),
41    drop: Option<Box<dyn DropRaw + 'a>>,
42    _marker: std::marker::PhantomData<&'a mut ()>,
43}
44
45unsafe impl Send for AnyProps<'_> {}
46unsafe impl Sync for AnyProps<'_> {}
47
48impl<'a> AnyProps<'a> {
49    // 创建拥有所有权的AnyProps实例
50    // T: 实现Props trait的类型
51    pub(crate) fn owned<T>(props: T) -> Self
52    where
53        T: Props + 'a,
54    {
55        // 将属性堆分配并转换为原始指针
56        let raw = Box::into_raw(Box::new(props));
57        Self {
58            raw: raw as *mut (),
59            // 保存对应的drop处理实现
60            drop: Some(Box::new(DropRowImpl::<T> {
61                _marker: std::marker::PhantomData,
62            })),
63            _marker: std::marker::PhantomData,
64        }
65    }
66
67    // 创建借用的AnyProps实例
68    // 不持有所有权,不负责内存释放
69    pub(crate) fn borrowed<T: Props>(props: &'a mut T) -> Self {
70        Self {
71            raw: props as *const _ as *mut (),
72            drop: None, // 不负责内存释放
73            _marker: std::marker::PhantomData,
74        }
75    }
76
77    // 创建只读借用版本
78    // drop字段设为None表示不处理内存释放
79    pub(crate) fn borrow(&mut self) -> Self {
80        Self {
81            raw: self.raw,
82            drop: None,
83            _marker: std::marker::PhantomData,
84        }
85    }
86
87    // 不安全的下转型方法(不可变引用)
88    // 调用者必须确保实际类型与T匹配
89    pub(crate) unsafe fn downcast_ref_unchecked<T: Props>(&self) -> &T {
90        unsafe { &*(self.raw as *const T) }
91    }
92
93    // 不安全的下转型方法(可变引用)
94    // 调用者必须确保实际类型与T匹配
95    pub(crate) unsafe fn downcast_mut_unchecked<T: Props>(&mut self) -> &mut T {
96        unsafe { &mut *(self.raw as *mut T) }
97    }
98}
99
100// 实现Drop trait用于资源释放
101impl Drop for AnyProps<'_> {
102    fn drop(&mut self) {
103        // 如果存在drop处理器,执行内存释放
104        if let Some(drop) = self.drop.take() {
105            drop.drop_raw(self.raw);
106        }
107    }
108}
109
110#[derive(Debug, Clone, Default, Props)]
111/// 空属性类型,表示组件不需要任何 props。
112///
113/// 可用于无参数组件或默认占位。
114pub struct NoProps;