Skip to main content

react_rs_core/
runtime.rs

1use std::cell::RefCell;
2use std::collections::VecDeque;
3use std::rc::Rc;
4
5thread_local! {
6    pub static RUNTIME: RefCell<Runtime> = RefCell::new(Runtime::new());
7}
8
9type EffectId = usize;
10type EffectFn = Rc<dyn Fn()>;
11
12pub struct Runtime {
13    effects: Vec<Option<EffectFn>>,
14    current_effect: Option<EffectId>,
15    pending_effects: VecDeque<EffectId>,
16    is_batching: bool,
17}
18
19impl Runtime {
20    pub fn new() -> Self {
21        Self {
22            effects: Vec::new(),
23            current_effect: None,
24            pending_effects: VecDeque::new(),
25            is_batching: false,
26        }
27    }
28
29    pub fn current_effect(&self) -> Option<EffectId> {
30        self.current_effect
31    }
32
33    pub fn register_effect(&mut self, f: impl Fn() + 'static) -> EffectId {
34        let id = self.effects.len();
35        self.effects.push(Some(Rc::new(f)));
36        id
37    }
38
39    pub fn set_current_effect(&mut self, id: Option<EffectId>) -> Option<EffectId> {
40        let prev = self.current_effect;
41        self.current_effect = id;
42        prev
43    }
44
45    pub fn get_effect(&self, id: EffectId) -> Option<&EffectFn> {
46        self.effects.get(id).and_then(|e| e.as_ref())
47    }
48
49    pub fn clone_effect(&self, id: EffectId) -> Option<EffectFn> {
50        self.effects.get(id).and_then(|e| e.as_ref().map(Rc::clone))
51    }
52
53    pub fn schedule_effect(&mut self, id: EffectId) {
54        if !self.pending_effects.contains(&id) {
55            self.pending_effects.push_back(id);
56        }
57    }
58
59    pub fn is_batching(&self) -> bool {
60        self.is_batching
61    }
62
63    pub fn pop_pending_effect(&mut self) -> Option<EffectId> {
64        self.pending_effects.pop_front()
65    }
66
67    pub fn start_batch(&mut self) -> bool {
68        let was_batching = self.is_batching;
69        self.is_batching = true;
70        was_batching
71    }
72
73    pub fn end_batch(&mut self, was_batching: bool) {
74        self.is_batching = was_batching;
75    }
76}
77
78impl Default for Runtime {
79    fn default() -> Self {
80        Self::new()
81    }
82}