use crate::{ProgramCollect, program::Program}; /// Trait for defining initialization/setup logic for a `Program`. /// /// Implementors can define custom setup behavior that will be executed /// when the program is initialized via [`Program::with_setup`]. /// /// # Type Parameters /// /// * `C` - The program collect type, which must implement [`ProgramCollect`] /// and have `Enum = C` (i.e., it collects itself). pub trait ProgramSetup where C: ProgramCollect, { /// Perform setup on the given program. /// /// This method consumes the setup instance (`self`) and is called once /// during program initialization. /// /// # Arguments /// /// * `program` - A mutable reference to the [`Program`] being set up. fn setup(self, program: &mut Program); } impl Program where C: ProgramCollect, { /// Load and execute init logic pub fn with_setup + 'static>(&mut self, setup: S) { S::setup(setup, self); } } #[cfg(test)] mod tests { use super::*; use crate::MockProgramCollect; struct TestSetup { called: std::rc::Rc>, } impl ProgramSetup for TestSetup { fn setup(self, _program: &mut Program) { self.called.set(true); } } #[test] fn test_with_setup_calls_setup() { let called = std::rc::Rc::new(std::cell::Cell::new(false)); let setup = TestSetup { called: std::rc::Rc::clone(&called), }; let mut program: Program = Program::new_with_args(["test"]); program.with_setup(setup); assert!(called.get()); } }