//! An example involving a coffee machine use std::{ cell::RefCell, rc::Rc, sync::{Arc, RwLock}, }; use dirk_framework::{component, component::StaticComponent, provides, use_provides}; use heater::Heater; use pump::Pump; #[use_provides(scoped_inject)] use heater::ElectricHeater; #[use_provides(singleton_inject)] use logger::CoffeeLogger; #[use_provides(scoped_inject)] use pump::ThermoSiphon; fn main() { let coffee_shop = DirkCoffeeShop::create(); coffee_shop.maker().brew(); coffee_shop .logger() .read() .unwrap() .logs() .iter() .for_each(|l| println!("{l}")); } #[component( logger: singleton_bind(CoffeeLogger), heater: scoped_bind(ElectricHeater) [logger], pump: scoped_bind(ThermoSiphon) [logger, heater], maker: static_bind(CoffeeMaker>) [logger, heater, pump] )] trait CoffeeShop { fn maker(&self) -> CoffeeMaker; fn logger(&self) -> Arc>; } //###################################################################################################################### struct CoffeeMaker { logger: Arc>, heater: Rc>, pump: Rc>, } #[provides] impl CoffeeMaker { fn new( logger: Arc>, heater: Rc>, pump: Rc>, ) -> Self { Self { logger, heater, pump, } } } impl CoffeeMaker { fn brew(&mut self) { self.heater.borrow_mut().on(); self.pump.borrow_mut().pump(); self.logger .write() .unwrap() .log(" [_]P coffee! [_]P ".to_owned()); self.heater.borrow_mut().off(); } } mod logger { use dirk_framework::provides; pub struct CoffeeLogger { logs: Vec, } #[provides(singleton_inject)] impl CoffeeLogger { fn new() -> Self { Self { logs: Vec::new() } } } impl CoffeeLogger { pub fn log(&mut self, msg: String) { self.logs.push(msg); } pub fn logs(&self) -> &Vec { &self.logs } } } mod heater { use dirk_framework::provides; use crate::logger::CoffeeLogger; use std::sync::{Arc, RwLock}; pub trait Heater { fn on(&mut self); fn off(&mut self); fn is_hot(&self) -> bool; } pub struct ElectricHeater { logger: Arc>, heating: bool, } #[provides(scoped_inject)] impl ElectricHeater { fn new(logger: Arc>) -> Self { Self { logger, heating: false, } } } impl Heater for ElectricHeater { fn on(&mut self) { self.heating = true; self.logger .write() .unwrap() .log("~ ~ ~ heating ~ ~ ~".to_owned()); } fn off(&mut self) { self.heating = false; } fn is_hot(&self) -> bool { self.heating } } } mod pump { use dirk_framework::provides; use crate::{heater::Heater, logger::CoffeeLogger}; use std::{ cell::RefCell, rc::Rc, sync::{Arc, RwLock}, }; pub trait Pump { fn pump(&mut self); } pub struct ThermoSiphon { logger: Arc>, heater: Rc>, } #[provides(scoped_inject)] impl ThermoSiphon { fn new(logger: Arc>, heater: Rc>) -> Self { Self { logger, heater } } } impl Pump for ThermoSiphon { fn pump(&mut self) { if self.heater.borrow().is_hot() { self.logger .write() .unwrap() .log("=> => pumping => =>".to_owned()); } } } }