hojicha_runtime/
safe_priority.rs1use crate::priority_queue::Priority;
7use hojicha_core::core::Message;
8use hojicha_core::event::Event;
9
10pub fn detect_priority<M: Message>(event: &Event<M>) -> Priority {
12 if event.is_quit() || event.is_key() || event.is_suspend() || event.is_resume() {
14 Priority::High
15 } else if event.is_resize() || event.is_tick() {
16 Priority::Low
17 } else {
18 Priority::Normal
19 }
20}
21
22#[derive(Debug, Clone)]
27pub enum EventKind {
28 Quit,
30 Key,
32 Mouse,
34 User,
36 Resize,
38 Tick,
40 Paste,
42 Focus,
44 Blur,
46 Suspend,
48 Resume,
50 ExecProcess,
52}
53
54impl EventKind {
55 pub fn priority(&self) -> Priority {
57 match self {
58 EventKind::Quit => Priority::High,
59 EventKind::Key => Priority::High,
60 EventKind::Suspend => Priority::High,
61 EventKind::Resume => Priority::High,
62
63 EventKind::Mouse => Priority::Normal,
64 EventKind::User => Priority::Normal,
65 EventKind::Paste => Priority::Normal,
66 EventKind::Focus => Priority::Normal,
67 EventKind::Blur => Priority::Normal,
68 EventKind::ExecProcess => Priority::Normal,
69
70 EventKind::Resize => Priority::Low,
71 EventKind::Tick => Priority::Low,
72 }
73 }
74
75 pub fn from_event<M: Message>(event: &Event<M>) -> Self {
77 if event.is_quit() {
78 EventKind::Quit
79 } else if event.is_key() {
80 EventKind::Key
81 } else if event.is_mouse() {
82 EventKind::Mouse
83 } else if event.is_user() {
84 EventKind::User
85 } else if event.is_resize() {
86 EventKind::Resize
87 } else if event.is_tick() {
88 EventKind::Tick
89 } else if event.is_paste() {
90 EventKind::Paste
91 } else if event.is_focus() {
92 EventKind::Focus
93 } else if event.is_blur() {
94 EventKind::Blur
95 } else if event.is_suspend() {
96 EventKind::Suspend
97 } else if event.is_resume() {
98 EventKind::Resume
99 } else {
100 EventKind::ExecProcess
101 }
102 }
103}
104
105pub trait SafePriorityMapper<M: Message>: Send + Sync {
107 fn map_priority(&self, event: &Event<M>) -> Priority;
109}
110
111pub struct DefaultPriorityMapper;
113
114impl<M: Message> SafePriorityMapper<M> for DefaultPriorityMapper {
115 fn map_priority(&self, event: &Event<M>) -> Priority {
116 detect_priority(event)
117 }
118}
119
120type PriorityMapperFn<M> = Box<dyn Fn(&Event<M>) -> Option<Priority> + Send + Sync>;
122
123pub struct CustomPriorityMapper<M: Message> {
125 mapper: PriorityMapperFn<M>,
126}
127
128impl<M: Message> CustomPriorityMapper<M> {
129 pub fn new<F>(mapper: F) -> Self
131 where
132 F: Fn(&Event<M>) -> Option<Priority> + Send + Sync + 'static,
133 {
134 Self {
135 mapper: Box::new(mapper),
136 }
137 }
138}
139
140impl<M: Message> SafePriorityMapper<M> for CustomPriorityMapper<M> {
141 fn map_priority(&self, event: &Event<M>) -> Priority {
142 (self.mapper)(event).unwrap_or_else(|| detect_priority(event))
144 }
145}
146
147#[cfg(test)]
148mod tests {
149 use super::*;
150 use hojicha_core::event::{Event, Key, KeyEvent, KeyModifiers};
151
152 #[test]
153 fn test_priority_detection() {
154 assert_eq!(detect_priority::<()>(&Event::Quit), Priority::High);
156 assert_eq!(
157 detect_priority::<()>(&Event::Key(KeyEvent::new(
158 Key::Char('a'),
159 KeyModifiers::empty()
160 ))),
161 Priority::High
162 );
163
164 assert_eq!(
166 detect_priority::<String>(&Event::User("test".to_string())),
167 Priority::Normal
168 );
169
170 assert_eq!(detect_priority::<()>(&Event::Tick), Priority::Low);
172 assert_eq!(
173 detect_priority::<()>(&Event::Resize {
174 width: 80,
175 height: 24
176 }),
177 Priority::Low
178 );
179 }
180
181 #[test]
182 fn test_event_kind() {
183 let quit_event: Event<()> = Event::Quit;
184 assert_eq!(
185 EventKind::from_event(&quit_event).priority(),
186 Priority::High
187 );
188
189 let tick_event: Event<()> = Event::Tick;
190 assert_eq!(EventKind::from_event(&tick_event).priority(), Priority::Low);
191 }
192
193 #[test]
194 fn test_custom_mapper() {
195 let mapper = CustomPriorityMapper::new(|event| {
197 if event.is_user() {
198 Some(Priority::High)
199 } else {
200 None
201 }
202 });
203
204 let user_event = Event::User("important".to_string());
205 assert_eq!(mapper.map_priority(&user_event), Priority::High);
206
207 let tick_event: Event<String> = Event::Tick;
208 assert_eq!(mapper.map_priority(&tick_event), Priority::Low);
209 }
210}