use std::sync::{Arc, Weak};
use crate::*;
#[derive(Clone)]
pub struct CatalogWeakRef(Arc<[std::sync::Weak<CatalogImpl>]>);
impl CatalogWeakRef {
pub(crate) fn new(pimpl: &std::sync::Arc<CatalogImpl>) -> Self {
let mut len = 0;
let mut current = Some(pimpl);
while let Some(p) = current {
len += 1;
current = p.chained_catalog.as_ref();
}
let mut refs = Vec::with_capacity(len);
let mut current = Some(pimpl);
while let Some(p) = current {
refs.push(Arc::downgrade(p));
current = p.chained_catalog.as_ref();
}
Self(refs.into())
}
pub fn upgrade(&self) -> Catalog {
for p in self.0.as_ref() {
if let Some(pimpl) = Weak::upgrade(p) {
return Catalog::new(pimpl);
}
}
panic!("Catalog was already dropped")
}
#[inline(always)]
pub fn get<Spec>(&self) -> Result<Spec::ReturnType, InjectionError>
where
Spec: DependencySpec + 'static,
{
self.get_with_context::<Spec>(&InjectionContext::new_root())
}
#[inline(always)]
pub fn get_with_context<Spec>(
&self,
ctx: &InjectionContext,
) -> Result<Spec::ReturnType, InjectionError>
where
Spec: DependencySpec + 'static,
{
let cat = self.upgrade();
Spec::get(&cat, &ctx.push_resolve::<Spec>())
}
#[inline(always)]
pub fn get_one<Iface>(&self) -> Result<Arc<Iface>, InjectionError>
where
Iface: 'static + ?Sized + Send + Sync,
{
self.get::<OneOf<Iface>>()
}
}
impl std::fmt::Debug for CatalogWeakRef {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for p in self.0.as_ref() {
if let Some(p) = p.upgrade() {
return write!(
f,
"CatalogWeakRef(0x{:x})",
p.as_ref() as *const CatalogImpl as usize
);
}
}
write!(f, "CatalogWeakRef(<dropped>)")
}
}