1use std::{
9 any::Any,
10 cell::{Ref, RefCell, RefMut},
11};
12
13pub 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 pub fn owned<T: Any + Send + Sync>(context: T) -> Self {
23 Context::Owned(Box::new(context))
24 }
25
26 pub fn form_ref<T: Any + Send + Sync>(context: &'a T) -> Self {
28 Context::Ref(context)
29 }
30
31 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 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 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}