froodi 1.0.0-beta.18

An ergonomic Rust IoC container
Documentation
use alloc::collections::vec_deque::VecDeque;
use core::mem;

use crate::{
    any::{Map, TypeInfo},
    utils::thread_safety::{RcAnyThreadSafety, RcThreadSafety, SendSafety, SyncSafety},
    Context,
};

#[derive(Clone)]
pub(crate) struct Cache {
    pub(crate) map: Map,
    pub(crate) resolved: ResolvedSet,
}

impl Cache {
    #[inline]
    #[must_use]
    pub fn new() -> Self {
        Self {
            map: Map::new(),
            resolved: ResolvedSet::new(),
        }
    }

    #[inline]
    pub(crate) fn insert_rc<T: SendSafety + SyncSafety + 'static>(
        &mut self,
        type_info: TypeInfo,
        value: RcThreadSafety<T>,
    ) -> Option<RcThreadSafety<T>> {
        self.map.insert(type_info, value).and_then(|boxed| boxed.downcast().ok())
    }

    #[inline]
    pub(crate) fn extend_context(&mut self, context: &Context) {
        self.map
            .extend(context.map.iter().map(|(type_info, value)| (type_info.clone(), value.clone())));
    }

    #[inline]
    #[must_use]
    pub(crate) fn child(&self) -> Self {
        Self {
            map: self.map.clone(),
            resolved: ResolvedSet::new(),
        }
    }

    #[must_use]
    pub(crate) fn get<T: SendSafety + SyncSafety + 'static>(&self, type_info: &TypeInfo) -> Option<RcThreadSafety<T>> {
        self.map.get(type_info).and_then(|boxed| boxed.clone().downcast().ok())
    }

    #[inline]
    pub(crate) fn push_resolved(&mut self, resolved: Resolved) {
        self.resolved.push(resolved);
    }

    #[inline]
    #[must_use]
    pub(crate) fn take_resolved_set(&mut self) -> ResolvedSet {
        mem::take(&mut self.resolved)
    }
}

#[derive(Clone)]
pub(crate) struct Resolved {
    pub(crate) type_info: TypeInfo,
    pub(crate) dependency: RcAnyThreadSafety,
}

#[derive(Default, Clone)]
pub(crate) struct ResolvedSet(pub(crate) VecDeque<Resolved>);

impl ResolvedSet {
    pub(crate) fn new() -> Self {
        Self(VecDeque::new())
    }

    pub(crate) fn push(&mut self, resolved: Resolved) {
        self.0.push_back(resolved);
    }
}