ratatui_kit/
context.rs

1//! 上下文模块,提供全局/局部依赖注入能力,支持跨组件数据共享与生命周期管理。
2//!
3//! ## 主要类型
4//! - [`Context`]:通用上下文枚举,支持所有权、不可变/可变引用三种模式。
5//! - [`ContextStack`]:上下文栈,支持嵌套作用域和动态查找。
6//! - [`SystemContext`]:系统级上下文,控制全局退出等。
7
8use std::{
9    any::Any,
10    cell::{Ref, RefCell, RefMut},
11};
12
13/// 通用上下文类型,支持所有权、不可变引用、可变引用三种模式。
14pub enum Context<'a> {
15    Ref(&'a (dyn Any + Send + Sync)),
16    Mut(&'a mut (dyn Any + Send + Sync)),
17    Owned(Box<dyn Any + Send + Sync>),
18}
19
20impl<'a> Context<'a> {
21    /// 创建一个拥有所有权的上下文。
22    pub fn owned<T: Any + Send + Sync>(context: T) -> Self {
23        Context::Owned(Box::new(context))
24    }
25
26    /// 创建一个不可变引用的上下文。
27    pub fn form_ref<T: Any + Send + Sync>(context: &'a T) -> Self {
28        Context::Ref(context)
29    }
30
31    /// 创建一个可变引用的上下文。
32    pub fn form_mut<T: Any + Send + Sync>(context: &'a mut T) -> Self {
33        Context::Mut(context)
34    }
35
36    pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
37        match self {
38            Context::Ref(context) => context.downcast_ref(),
39            Context::Mut(context) => context.downcast_ref(),
40            Context::Owned(context) => context.downcast_ref(),
41        }
42    }
43
44    pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
45        match self {
46            Context::Ref(_) => None,
47            Context::Mut(context) => context.downcast_mut(),
48            Context::Owned(context) => context.downcast_mut(),
49        }
50    }
51
52    pub fn borrow(&mut self) -> Context {
53        match self {
54            Context::Ref(context) => Context::Ref(*context),
55            Context::Mut(context) => Context::Mut(*context),
56            Context::Owned(context) => Context::Mut(&mut **context),
57        }
58    }
59}
60
61pub struct ContextStack<'a> {
62    stack: Vec<RefCell<Context<'a>>>,
63}
64
65impl<'a> ContextStack<'a> {
66    pub(crate) fn root(root_context: &'a mut (dyn Any + Send + Sync)) -> Self {
67        ContextStack {
68            stack: vec![RefCell::new(Context::Mut(root_context))],
69        }
70    }
71    // 在上下文栈中临时插入一个新的上下文,并在闭包 f 执行期间可用。
72    pub(crate) fn with_context<'b, F>(&'b mut self, context: Option<Context<'b>>, f: F)
73    where
74        F: FnOnce(&mut ContextStack),
75    {
76        if let Some(context) = context {
77            // SAFETY: 可变引用在生命周期上是不变的,为了插入更短生命周期的上下文,需要对 'a 进行转变。
78            // 只有在不允许对栈进行其他更改,并且在调用后立即恢复栈的情况下才是安全的。
79            let shorter_lived_self =
80                unsafe { std::mem::transmute::<&mut Self, &mut ContextStack<'b>>(self) };
81            shorter_lived_self.stack.push(RefCell::new(context));
82            f(shorter_lived_self);
83            shorter_lived_self.stack.pop();
84        } else {
85            f(self);
86        };
87    }
88
89    pub fn get_context<T: Any>(&self) -> Option<Ref<T>> {
90        for context in self.stack.iter().rev() {
91            if let Ok(context) = context.try_borrow() {
92                if let Ok(res) = Ref::filter_map(context, |context| context.downcast_ref::<T>()) {
93                    return Some(res);
94                }
95            }
96        }
97        None
98    }
99
100    pub fn get_context_mut<T: Any>(&self) -> Option<RefMut<T>> {
101        for context in self.stack.iter().rev() {
102            if let Ok(context) = context.try_borrow_mut() {
103                if let Ok(res) = RefMut::filter_map(context, |context| context.downcast_mut::<T>())
104                {
105                    return Some(res);
106                }
107            }
108        }
109        None
110    }
111}
112
113pub struct SystemContext {
114    should_exit: bool,
115}
116
117unsafe impl Send for SystemContext {}
118unsafe impl Sync for SystemContext {}
119
120impl SystemContext {
121    pub(crate) fn new() -> Self {
122        Self { should_exit: false }
123    }
124
125    pub(crate) fn should_exit(&self) -> bool {
126        self.should_exit
127    }
128
129    pub fn exit(&mut self) {
130        self.should_exit = true;
131    }
132}