cu29_runtime/
app.rs

1use crate::curuntime::KeyFrame;
2use cu29_clock::RobotClock;
3use cu29_traits::CuResult;
4use cu29_unifiedlog::{SectionStorage, UnifiedLogWrite};
5
6#[cfg(not(feature = "std"))]
7mod imp {
8    pub use alloc::string::String;
9    pub use alloc::sync::Arc;
10    pub use spin::Mutex;
11}
12
13#[cfg(feature = "std")]
14mod imp {
15    pub use crate::config::CuConfig;
16    pub use crate::simulation::SimOverride;
17    pub use cu29_unifiedlog::memmap::MmapSectionStorage;
18    pub use std::sync::{Arc, Mutex};
19}
20
21use imp::*;
22
23/// Convenience trait for CuApplication when it is just a std App
24#[cfg(feature = "std")]
25pub trait CuStdApplication:
26    CuApplication<MmapSectionStorage, cu29_unifiedlog::UnifiedLoggerWrite>
27{
28}
29
30#[cfg(feature = "std")]
31impl<T> CuStdApplication for T where
32    T: CuApplication<MmapSectionStorage, cu29_unifiedlog::UnifiedLoggerWrite>
33{
34}
35
36/// A trait that defines the structure and behavior of a CuApplication.
37///
38/// CuApplication is the normal, running on robot version of an application and its runtime.
39///
40/// The `CuApplication` trait outlines the necessary functions required for managing an application lifecycle,
41/// including configuration management, initialization, task execution, and runtime control. It is meant to be
42/// implemented by types that represent specific applications, providing them with unified control and execution features.
43///
44/// This is the more generic version that allows you to specify a custom unified logger.
45pub trait CuApplication<S: SectionStorage, L: UnifiedLogWrite<S> + 'static> {
46    /// Returns the original configuration as a string, typically loaded from a RON file.
47    /// This configuration represents the default settings for the application before any overrides.
48    fn get_original_config() -> String;
49
50    /// Creates a new application.
51    ///
52    /// # Arguments
53    ///
54    /// * `clock` - A `RobotClock` instance to be used for time-related operations in the implementing struct.
55    /// * `unified_logger` - A thread-safe, shared reference to `UnifiedLoggerWrite`, enabling logging functionalities.
56    /// * `config_override` - An optional `CuConfig` instance that allows overriding the default configuration values.
57    ///   - If `Some`, the provided configuration will be used.
58    ///   - If `None`, the default configuration will be applied.
59    ///
60    /// # Returns
61    ///
62    /// A result containing either:
63    /// - An instantiated object of the implementing type (`Self`), or
64    /// - A `CuResult` error in case of failure during initialization.
65    ///
66    fn new(
67        clock: RobotClock,
68        unified_logger: Arc<Mutex<L>>,
69        #[cfg(feature = "std")] config_override: Option<CuConfig>, // No config override in no-std, the bundled config is always the config
70    ) -> CuResult<Self>
71    where
72        Self: Sized;
73
74    /// Starts all tasks managed by the application/runtime.
75    ///
76    /// # Returns
77    /// * `Ok(())` - If all tasks are started successfully.
78    /// * `Err(CuResult)` - If an error occurs while attempting to start one
79    ///   or more tasks.
80    fn start_all_tasks(&mut self) -> CuResult<()>;
81
82    /// Executes a single iteration of copper-generated runtime (generating and logging one copperlist)
83    ///
84    /// # Returns
85    ///
86    /// * `CuResult<()>` - Returns `Ok(())` if the iteration completes successfully, or an error
87    ///   wrapped in `CuResult` if something goes wrong during execution.
88    ///
89    fn run_one_iteration(&mut self) -> CuResult<()>;
90
91    /// Runs indefinitely looping over run_one_iteration
92    ///
93    /// # Returns
94    ///
95    /// Returns a `CuResult<()>`, which indicates the success or failure of the
96    /// operation.
97    /// - On success, the result is `Ok(())`.
98    /// - On failure, an appropriate error wrapped in `CuResult` is returned.
99    fn run(&mut self) -> CuResult<()>;
100
101    /// Stops all tasks managed by the application/runtime.
102    ///
103    /// # Returns
104    ///
105    /// Returns a `CuResult<()>`, which indicates the success or failure of the
106    /// operation.
107    /// - On success, the result is `Ok(())`.
108    /// - On failure, an appropriate error wrapped in `CuResult` is returned.
109    ///
110    fn stop_all_tasks(&mut self) -> CuResult<()>;
111
112    /// Restore all tasks from the given frozen state
113    fn restore_keyframe(&mut self, freezer: &KeyFrame) -> CuResult<()>;
114}
115
116/// A trait that defines the structure and behavior of a simulation-enabled CuApplication.
117///
118/// CuSimApplication is the simulation version of an application and its runtime, allowing
119/// overriding of steps with simulated behavior.
120///
121/// The `CuSimApplication` trait outlines the necessary functions required for managing an application lifecycle
122/// in simulation mode, including configuration management, initialization, task execution, and runtime control.
123#[cfg(feature = "std")]
124pub trait CuSimApplication<S: SectionStorage, L: UnifiedLogWrite<S> + 'static> {
125    /// The type representing a simulation step that can be overridden
126    type Step<'z>;
127
128    /// Returns the original configuration as a string, typically loaded from a RON file.
129    /// This configuration represents the default settings for the application before any overrides.
130    fn get_original_config() -> String;
131
132    /// Creates a new simulation-enabled application.
133    ///
134    /// # Arguments
135    ///
136    /// * `clock` - A `RobotClock` instance to be used for time-related operations in the implementing struct.
137    /// * `unified_logger` - A thread-safe, shared reference to `UnifiedLoggerWrite`, enabling logging functionalities.
138    /// * `config_override` - An optional `CuConfig` instance that allows overriding the default configuration values.
139    ///   - If `Some`, the provided configuration will be used.
140    ///   - If `None`, the default configuration will be applied.
141    /// * `sim_callback` - A mutable function reference that allows overriding individual simulation steps.
142    ///   The callback receives a Step parameter and returns a SimOverride indicating how to handle the step.
143    ///
144    /// # Returns
145    ///
146    /// A result containing either:
147    /// - An instantiated object of the implementing type (`Self`), or
148    /// - A `CuResult` error in case of failure during initialization.
149    fn new(
150        clock: RobotClock,
151        unified_logger: Arc<Mutex<L>>,
152        config_override: Option<CuConfig>,
153        sim_callback: &mut impl for<'z> FnMut(Self::Step<'z>) -> SimOverride,
154    ) -> CuResult<Self>
155    where
156        Self: Sized;
157
158    /// Starts all tasks managed by the application/runtime in simulation mode.
159    ///
160    /// # Arguments
161    /// * `sim_callback` - A mutable function reference that allows overriding individual simulation steps.
162    ///
163    /// # Returns
164    /// * `Ok(())` - If all tasks are started successfully.
165    /// * `Err(CuResult)` - If an error occurs while attempting to start one
166    ///   or more tasks.
167    fn start_all_tasks(
168        &mut self,
169        sim_callback: &mut impl for<'z> FnMut(Self::Step<'z>) -> SimOverride,
170    ) -> CuResult<()>;
171
172    /// Executes a single iteration of copper-generated runtime in simulation mode.
173    ///
174    /// # Arguments
175    /// * `sim_callback` - A mutable function reference that allows overriding individual simulation steps.
176    ///
177    /// # Returns
178    ///
179    /// * `CuResult<()>` - Returns `Ok(())` if the iteration completes successfully, or an error
180    ///   wrapped in `CuResult` if something goes wrong during execution.
181    fn run_one_iteration(
182        &mut self,
183        sim_callback: &mut impl for<'z> FnMut(Self::Step<'z>) -> SimOverride,
184    ) -> CuResult<()>;
185
186    /// Runs indefinitely looping over run_one_iteration in simulation mode
187    ///
188    /// # Arguments
189    /// * `sim_callback` - A mutable function reference that allows overriding individual simulation steps.
190    ///
191    /// # Returns
192    ///
193    /// Returns a `CuResult<()>`, which indicates the success or failure of the
194    /// operation.
195    /// - On success, the result is `Ok(())`.
196    /// - On failure, an appropriate error wrapped in `CuResult` is returned.
197    fn run(
198        &mut self,
199        sim_callback: &mut impl for<'z> FnMut(Self::Step<'z>) -> SimOverride,
200    ) -> CuResult<()>;
201
202    /// Stops all tasks managed by the application/runtime in simulation mode.
203    ///
204    /// # Arguments
205    /// * `sim_callback` - A mutable function reference that allows overriding individual simulation steps.
206    ///
207    /// # Returns
208    ///
209    /// Returns a `CuResult<()>`, which indicates the success or failure of the
210    /// operation.
211    /// - On success, the result is `Ok(())`.
212    /// - On failure, an appropriate error wrapped in `CuResult` is returned.
213    fn stop_all_tasks(
214        &mut self,
215        sim_callback: &mut impl for<'z> FnMut(Self::Step<'z>) -> SimOverride,
216    ) -> CuResult<()>;
217
218    /// Restore all tasks from the given frozen state
219    fn restore_keyframe(&mut self, freezer: &KeyFrame) -> CuResult<()>;
220}