Skip to main content

ratatui_kit/hooks/
use_context.rs

1use std::{
2    any::{Any, type_name},
3    cell::{Ref, RefMut},
4};
5
6use super::Hooks;
7use crate::context::ContextLookup;
8
9mod private {
10    pub trait Sealed {}
11
12    impl Sealed for crate::hooks::Hooks<'_, '_> {}
13}
14
15pub trait UseContext<'a>: private::Sealed {
16    // 获取全局/局部上下文,实现依赖注入。适合主题、配置、全局状态等场景。
17    fn use_context<T: Any>(&self) -> Ref<'a, T>;
18    // 获取可变上下文。
19    fn use_context_mut<T: Any>(&self) -> RefMut<'a, T>;
20    // 尝试获取只读上下文,返回 Option。
21    fn try_use_context<T: Any>(&self) -> Option<Ref<'a, T>>;
22    // 尝试获取可变上下文,返回 Option。
23    fn try_use_context_mut<T: Any>(&self) -> Option<RefMut<'a, T>>;
24}
25
26impl<'a> UseContext<'a> for Hooks<'a, '_> {
27    fn use_context<T: Any>(&self) -> Ref<'a, T> {
28        let stack = self.context.expect("context not available");
29        match stack.get_context::<T>() {
30            ContextLookup::Found(res) => res,
31            ContextLookup::AlreadyBorrowed => panic!(
32                "context `{}` 已被借用,请先释放现有 context 守卫",
33                type_name::<T>()
34            ),
35            ContextLookup::NotFound => panic!("context `{}` not found", type_name::<T>()),
36        }
37    }
38
39    fn use_context_mut<T: Any>(&self) -> RefMut<'a, T> {
40        let stack = self.context.expect("context not available");
41        match stack.get_context_mut::<T>() {
42            ContextLookup::Found(res) => res,
43            ContextLookup::AlreadyBorrowed => panic!(
44                "context `{}` 已被借用,请先释放现有 context 守卫",
45                type_name::<T>()
46            ),
47            ContextLookup::NotFound => panic!("context `{}` not found", type_name::<T>()),
48        }
49    }
50
51    fn try_use_context<T: Any>(&self) -> Option<Ref<'a, T>> {
52        match self.context?.get_context::<T>() {
53            ContextLookup::Found(res) => Some(res),
54            _ => None,
55        }
56    }
57
58    fn try_use_context_mut<T: Any>(&self) -> Option<RefMut<'a, T>> {
59        match self.context?.get_context_mut::<T>() {
60            ContextLookup::Found(res) => Some(res),
61            _ => None,
62        }
63    }
64}