use alloc::vec::Vec;
use super::World;
pub struct System {
pub name: &'static str,
pub priority: i32,
pub run: fn(&mut World),
}
impl System {
pub const fn new(name: &'static str, priority: i32, run: fn(&mut World)) -> Self {
Self {
name,
priority,
run,
}
}
}
pub mod run_order {
pub const SIM_INPUT: i32 = 50;
pub const DELTA_TIME: i32 = 60;
pub const ANIMATION: i32 = 150;
pub const TIMER: i32 = 150;
pub const SCROLL_INERTIA: i32 = 250;
pub const LAZY_LIST: i32 = 350;
pub const TAB_PAGES: i32 = 350;
pub const NORMAL: i32 = 500;
}
#[derive(Default)]
pub struct SystemScheduler {
systems: Vec<System>,
}
impl SystemScheduler {
pub fn new() -> Self {
Self::default()
}
pub fn add(&mut self, system: System) {
let pos = self
.systems
.iter()
.position(|s| s.priority > system.priority)
.unwrap_or(self.systems.len());
self.systems.insert(pos, system);
}
pub fn run_all(&mut self, world: &mut World) {
for system in &self.systems {
(system.run)(world);
}
}
pub fn iter(&self) -> impl Iterator<Item = &System> {
self.systems.iter()
}
}
#[cfg(test)]
mod tests {
use super::*;
fn dummy(_: &mut World) {}
#[test]
fn run_order_orders_ascending() {
let mut s = SystemScheduler::new();
s.add(System::new("late", 300, dummy));
s.add(System::new("early", 100, dummy));
s.add(System::new("mid", 200, dummy));
let names: Vec<&str> = s.iter().map(|s| s.name).collect();
assert_eq!(names, ["early", "mid", "late"]);
}
#[test]
fn equal_run_order_preserves_insertion_order() {
let mut s = SystemScheduler::new();
s.add(System::new("a", 200, dummy));
s.add(System::new("b", 200, dummy));
s.add(System::new("c", 100, dummy));
let names: Vec<&str> = s.iter().map(|s| s.name).collect();
assert_eq!(names, ["c", "a", "b"]);
}
}