noema 0.4.0

Noema IOC and DI framework for Rust
Documentation
use std::future::Future;
use std::pin::Pin;
use std::sync::{Arc, RwLock};

use super::{ConfigError, ConfigSource};

/// Async hydrate registered by [`config!`](crate::config).
pub type HydrateFn =
    fn(Arc<dyn ConfigSource>) -> Pin<Box<dyn Future<Output = Result<(), ConfigError>> + Send>>;

static REGISTRY: RwLock<Vec<HydrateFn>> = RwLock::new(Vec::new());

/// Push a hydrate fn. Invoked by [`config!`](crate::config) via `ctor`.
#[doc(hidden)]
pub fn register(hydrate: HydrateFn) {
    REGISTRY
        .write()
        .expect("config hydrate registry")
        .push(hydrate);
}

/// Prefetch `source`, then run every registered hydrate (sets each `OnceLock`).
///
/// Choose the implementation with runtime `if`s and pass it here. Call once per process.
pub async fn load(source: impl ConfigSource + 'static) -> Result<(), ConfigError> {
    let source: Arc<dyn ConfigSource> = Arc::new(source);
    source.load().await?;

    let hydrates = REGISTRY.read().expect("config hydrate registry").clone();

    for hydrate in hydrates {
        hydrate(source.clone()).await?;
    }
    Ok(())
}