concinnity_core/app/driver.rs
1//! The contract a host's loop implements, and the headless loop's own
2//! implementation of it.
3
4use alloc::boxed::Box;
5
6use crate::app::App;
7use crate::ecs::World;
8use crate::result::CnResult;
9
10/// A loop that runs a [`World`].
11///
12/// [`App`] is the implementation with nothing underneath it: a fixed virtual
13/// timestep, no window, and no wall clock. A host that has an operating system
14/// implements this over its own loop, and what such a host adds -- pacing a
15/// frame against a display, following real elapsed time, catching a signal --
16/// stays on its side of the seam.
17///
18/// [`run`](Driver::run) reports whether the run failed rather than how it
19/// ended. A [`StepResult`](crate::ecs::StepResult) is a system's verdict on its
20/// own tick, and a host ends a run for reasons no system sees, so a driver that
21/// reported one would owe readings for them.
22///
23/// `run` consumes the driver, since a run ends the world it was handed;
24/// [`into_world`](Driver::into_world) is the other way out, for a caller that
25/// wants the world back instead of run.
26pub trait Driver {
27 /// Build the world's systems and run their `init`.
28 fn start(&mut self) -> Result<(), CnResult>;
29
30 /// Run the world until it ends.
31 fn run(self: Box<Self>) -> Result<(), CnResult>;
32
33 /// Take the world back instead of running it.
34 fn into_world(self: Box<Self>) -> World;
35}
36
37impl Driver for App {
38 fn start(&mut self) -> Result<(), CnResult> {
39 App::start(self)
40 }
41
42 fn run(mut self: Box<Self>) -> Result<(), CnResult> {
43 App::run(&mut self).map(|_| ())
44 }
45
46 fn into_world(self: Box<Self>) -> World {
47 self.world
48 }
49}