galvyn-core 0.4.0

Core concepts for galvyn like trait definitions
use std::any::Any;

use tokio::sync::SetOnce;
use tokio::task::JoinHandle;

pub use self::dependencies::ModuleDependencies;
use crate::module;
use crate::module::Module;
use crate::module::registry::builder::RegistryBuilder;
use crate::module::registry::module_set::LeakedModuleSet;

pub mod builder;
mod dependencies;
mod module_set;

/// The registry stores [`Module`]s
///
/// is responsible for their initialization and grants access to them.
pub struct Registry {
    modules: LeakedModuleSet,
}

trait DynModule: Any + Send + Sync + 'static {
    #[doc(hidden)]
    fn post_init(&'static self) -> (&'static str, JoinHandle<Result<(), module::PostInitError>>);
}

impl Registry {
    pub fn builder() -> RegistryBuilder {
        RegistryBuilder::new()
    }

    #[track_caller]
    pub fn global() -> &'static Self {
        let Some(global) = Self::raw_global().get() else {
            panic!("The global registry has not been initialized yet.");
        };
        global
    }

    pub async fn global_wait() -> &'static Self {
        Self::raw_global().wait().await
    }

    pub fn try_global() -> Option<&'static Self> {
        Self::raw_global().get()
    }

    pub fn try_get<T: Module>(&self) -> Option<&T> {
        self.modules.get()
    }

    fn raw_global() -> &'static SetOnce<Self> {
        static GLOBAL: SetOnce<Registry> = SetOnce::const_new();
        &GLOBAL
    }
}