use super::*;
impl Injector {
pub(crate) fn store_instance<T>(&self, instance: Shared<Instance<T>>)
where
T: ?Sized + Send + Sync + 'static,
{
let type_id = TypeId::of::<T>();
#[cfg(feature = "tracing")]
let type_name = std::any::type_name::<T>();
#[cfg(feature = "lock-free")]
{
self.inner.instances.insert(type_id, instance);
}
#[cfg(not(feature = "lock-free"))]
{
self.inner
.instances
.write()
.unwrap()
.insert(type_id, instance);
}
#[cfg(feature = "tracing")]
trace!(
type_name = type_name,
op = "instance_store",
"Stored resolved instance in cache"
);
}
pub(crate) fn store_set_instance<T>(
&self,
provider_ref: &Shared<Provider<T>>,
instance: Shared<Instance<T>>,
) where
T: ?Sized + Send + Sync + 'static,
{
let key = SetProviderKey::of::<T>(provider_ref);
#[cfg(feature = "tracing")]
let type_name = std::any::type_name::<T>();
#[cfg(feature = "lock-free")]
{
self.inner.set_instances.insert(key, instance);
}
#[cfg(not(feature = "lock-free"))]
{
self.inner
.set_instances
.write()
.unwrap()
.insert(key, instance);
}
#[cfg(feature = "tracing")]
trace!(
type_name = type_name,
op = "instance_store_set",
provider_ptr = key.provider_ptr,
"Stored set-binding instance in cache"
);
}
pub(crate) fn store_instance_named<T>(&self, name: &str, instance: Shared<Instance<T>>)
where
T: ?Sized + Send + Sync + 'static,
{
let key = NamedTypeKey::of::<T>(name);
#[cfg(feature = "tracing")]
let type_name = std::any::type_name::<T>();
#[cfg(feature = "lock-free")]
{
self.inner.named_instances.insert(key, instance);
}
#[cfg(not(feature = "lock-free"))]
{
self.inner
.named_instances
.write()
.unwrap()
.insert(key, instance);
}
#[cfg(feature = "tracing")]
trace!(
type_name = type_name,
name = %name,
op = "instance_store_named",
"Stored named instance in cache"
);
}
pub(crate) fn store_provider<T>(&self, provider: Provider<T>) -> Result<(), Error>
where
T: ?Sized + Send + Sync + 'static,
{
let type_id = TypeId::of::<T>();
let type_name = std::any::type_name::<T>();
let scope = provider.scope;
let scope_text = scope.to_string();
let graph_meta = ProviderGraphMeta::of::<T>(scope, provider.dependency_hints.clone());
#[cfg(feature = "tracing")]
debug!(
type_name = type_name,
scope = %scope,
op = "provider_store",
"Storing provider definition"
);
#[cfg(feature = "lock-free")]
{
match self.inner.providers.entry(type_id) {
DashEntry::Occupied(_) => {
#[cfg(feature = "tracing")]
debug!(
type_name = type_name,
scope = %scope,
op = "provider_store",
"Provider registration rejected: duplicate binding"
);
return Err(Error::provider_already_registered(
type_name,
scope_text.as_str(),
));
}
DashEntry::Vacant(entry) => {
entry.insert(Shared::new(provider));
}
}
self.inner.graph_providers.insert(type_id, graph_meta);
}
#[cfg(not(feature = "lock-free"))]
{
let mut providers = self.inner.providers.write().unwrap();
if providers.contains_key(&type_id) {
#[cfg(feature = "tracing")]
debug!(
type_name = type_name,
scope = %scope,
op = "provider_store",
"Provider registration rejected: duplicate binding"
);
return Err(Error::provider_already_registered(
type_name,
scope_text.as_str(),
));
}
providers.insert(type_id, Shared::new(provider));
drop(providers);
self.inner
.graph_providers
.write()
.unwrap()
.insert(type_id, graph_meta);
}
#[cfg(feature = "tracing")]
debug!(
type_name = type_name,
scope = %scope,
op = "provider_store",
"Provider definition stored"
);
Ok(())
}
pub(crate) fn store_set_provider<T>(&self, provider: Provider<T>) -> Result<(), Error>
where
T: ?Sized + Send + Sync + 'static,
{
let type_id = TypeId::of::<T>();
#[cfg(feature = "tracing")]
let type_name = std::any::type_name::<T>();
#[cfg(feature = "tracing")]
let scope = provider.scope;
let graph_meta =
ProviderGraphMeta::of::<T>(provider.scope, provider.dependency_hints.clone());
#[cfg(feature = "lock-free")]
{
match self.inner.set_providers.entry(type_id) {
DashEntry::Occupied(mut entry) => {
entry.get_mut().push(Shared::new(provider));
}
DashEntry::Vacant(entry) => {
entry.insert(vec![Shared::new(provider)]);
}
}
match self.inner.graph_set_providers.entry(type_id) {
DashEntry::Occupied(mut entry) => {
entry.get_mut().push(graph_meta);
}
DashEntry::Vacant(entry) => {
entry.insert(vec![graph_meta]);
}
}
}
#[cfg(not(feature = "lock-free"))]
{
let mut providers = self.inner.set_providers.write().unwrap();
providers
.entry(type_id)
.or_default()
.push(Shared::new(provider));
drop(providers);
self.inner
.graph_set_providers
.write()
.unwrap()
.entry(type_id)
.or_default()
.push(graph_meta);
}
#[cfg(feature = "tracing")]
debug!(
type_name = type_name,
scope = %scope,
op = "provider_store_set",
"Provider appended to set binding"
);
Ok(())
}
}