/* //! Defines the [Step] struct which may be used when initialising the system. //! //! # Warning //! //! Use of alloc is currently required, so early initialisation will need a //! different method. We should possibly abstract some functionality so that //! consumers don't need to worry or care about the difference. use alloc::{borrow::ToOwned, boxed::Box, string::String, vec::Vec}; use crate::{arch::x86_64::drivers::ascii::WRITER, prelude::*}; /// Represents a [Step] when initialising the system. /// /// Handles printing various information to the framebuffer using steps. /// /// # Example /// /// ```rs /// // Setup a Step for Foo. /// let foo_step: Step = Step::new("foo", Foo::init()).register_tag(|foo| { foo.bar().to_string() }); /// // This returns a Result /// let foo = foo_step.run()?; /// ``` /// /// # TODOs /// /// * If T = Option and None is returned, we print `"[Not found]"`, otherwise /// `"[Success]`". pub struct Step { /// The initialisation function for the Step, usually this is a closure. init_fn: fn() -> T, /// A list of tag generator functions to display under the Step on success. /// They are displayed like: /// ``` /// Initialising module... [Success] /// => Some information here. /// ``` /// /// # TODOs /// /// * Support tags without alloc being initialised. tags: Vec String>>, /// The name of the module being initialised. task: &'static str, } // This impl block might be so horrible it needs its own file. impl Step { pub fn new( task: &'static str, init_fn: fn() -> T, tags: Vec String>>, ) -> Self { Self { init_fn, tags, task, } } /// Runs the initialisation function and logs where required. /// /// This function is a little messy but it just handles pretty printing the /// [Step] to the terminal for us. pub fn run(self) -> T { print_log!(" {}", self.task); let mut success_position = WRITER.lock().pos(); success_position.set_x(success_position.x() + 1); let ret = (self.init_fn)(); println!(); for tag in &self.tags[..] { // Calls the closure on the return value. println_log!(" => {}", (tag)(ret.clone())); } // Print whether or not the step succeeded. print_oneshot!( success_position, Colour::Green, Colour::Black, "[Success]" ); ret } /// Registers a 'tag' or note to display under the line which says /// `Initialising module... [Success]`. /// /// # Notes /// /// The tag is a closure taking in a reference to T and returning a /// presumably formatted String. #[allow(unused)] pub fn register_tag(&mut self, tag: Box String>) -> &Self { self.tags.push(tag); self } } */