1use std::{
2 any::Any,
3 cell::{Ref, RefCell, RefMut},
4};
5
6pub enum Context<'a> {
7 Ref(&'a (dyn Any + Send + Sync)),
8 Mut(&'a mut (dyn Any + Send + Sync)),
9 Owned(Box<dyn Any + Send + Sync>),
10}
11
12impl<'a> Context<'a> {
13 pub fn owned<T: Any + Send + Sync>(context: T) -> Self {
14 Context::Owned(Box::new(context))
15 }
16
17 pub fn form_ref<T: Any + Send + Sync>(context: &'a T) -> Self {
18 Context::Ref(context)
19 }
20
21 pub fn form_mut<T: Any + Send + Sync>(context: &'a mut T) -> Self {
22 Context::Mut(context)
23 }
24
25 pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
26 match self {
27 Context::Ref(context) => context.downcast_ref(),
28 Context::Mut(context) => context.downcast_ref(),
29 Context::Owned(context) => context.downcast_ref(),
30 }
31 }
32
33 pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
34 match self {
35 Context::Ref(_) => None,
36 Context::Mut(context) => context.downcast_mut(),
37 Context::Owned(context) => context.downcast_mut(),
38 }
39 }
40
41 pub fn borrow(&mut self) -> Context {
42 match self {
43 Context::Ref(context) => Context::Ref(*context),
44 Context::Mut(context) => Context::Mut(*context),
45 Context::Owned(context) => Context::Mut(&mut **context),
46 }
47 }
48}
49
50pub struct ContextStack<'a> {
51 stack: Vec<RefCell<Context<'a>>>,
52}
53
54impl<'a> ContextStack<'a> {
55 pub(crate) fn root(root_context: &'a mut (dyn Any + Send + Sync)) -> Self {
56 ContextStack {
57 stack: vec![RefCell::new(Context::Mut(root_context))],
58 }
59 }
60 pub(crate) fn with_context<'b, F>(&'b mut self, context: Option<Context<'b>>, f: F)
62 where
63 F: FnOnce(&mut ContextStack),
64 {
65 if let Some(context) = context {
66 let shorter_lived_self =
69 unsafe { std::mem::transmute::<&mut Self, &mut ContextStack<'b>>(self) };
70 shorter_lived_self.stack.push(RefCell::new(context));
71 f(shorter_lived_self);
72 shorter_lived_self.stack.pop();
73 } else {
74 f(self);
75 };
76 }
77
78 pub fn get_context<T: Any>(&self) -> Option<Ref<T>> {
79 for context in self.stack.iter().rev() {
80 if let Ok(context) = context.try_borrow() {
81 if let Ok(res) = Ref::filter_map(context, |context| context.downcast_ref::<T>()) {
82 return Some(res);
83 }
84 }
85 }
86 None
87 }
88
89 pub fn get_context_mut<T: Any>(&self) -> Option<RefMut<T>> {
90 for context in self.stack.iter().rev() {
91 if let Ok(context) = context.try_borrow_mut() {
92 if let Ok(res) = RefMut::filter_map(context, |context| context.downcast_mut::<T>())
93 {
94 return Some(res);
95 }
96 }
97 }
98 None
99 }
100}
101
102pub struct SystemContext {
103 should_exit: bool,
104}
105
106unsafe impl Send for SystemContext {}
107unsafe impl Sync for SystemContext {}
108
109impl SystemContext {
110 pub(crate) fn new() -> Self {
111 Self { should_exit: false }
112 }
113
114 pub(crate) fn should_exit(&self) -> bool {
115 self.should_exit
116 }
117
118 pub fn exit(&mut self) {
119 self.should_exit = true;
120 }
121}