use std::any::{Any, TypeId};
use std::sync::Arc;
use crate::SingletonScope;
type Registration = Box<dyn FnOnce(&SingletonScope) + Send + Sync>;
pub struct DiRegistrationList {
registrations: Vec<Registration>,
}
impl DiRegistrationList {
pub fn new() -> Self {
Self {
registrations: Vec::new(),
}
}
pub fn register_arc<T: Any + Send + Sync + 'static>(&mut self, value: Arc<T>) {
self.registrations
.push(Box::new(move |scope: &SingletonScope| {
scope.set_arc(value);
}));
}
pub fn register_arc_any(&mut self, type_id: TypeId, value: Arc<dyn Any + Send + Sync>) {
self.registrations
.push(Box::new(move |scope: &SingletonScope| {
scope.set_arc_any(type_id, value);
}));
}
pub fn register<T: Any + Send + Sync + 'static>(&mut self, value: T) {
self.registrations
.push(Box::new(move |scope: &SingletonScope| {
scope.set(value);
}));
}
pub fn apply_to(self, scope: &SingletonScope) {
for registration in self.registrations {
registration(scope);
}
}
pub fn merge(&mut self, other: DiRegistrationList) {
self.registrations.extend(other.registrations);
}
pub fn is_empty(&self) -> bool {
self.registrations.is_empty()
}
pub fn len(&self) -> usize {
self.registrations.len()
}
}
impl Default for DiRegistrationList {
fn default() -> Self {
Self::new()
}
}
impl std::fmt::Debug for DiRegistrationList {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DiRegistrationList")
.field("count", &self.registrations.len())
.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_empty_list() {
let list = DiRegistrationList::new();
assert!(list.is_empty());
assert_eq!(list.len(), 0);
}
#[test]
fn test_register_arc_and_apply() {
let mut list = DiRegistrationList::new();
list.register_arc(Arc::new(42i32));
list.register_arc(Arc::new("hello".to_string()));
assert_eq!(list.len(), 2);
let scope = SingletonScope::new();
list.apply_to(&scope);
assert_eq!(*scope.get::<i32>().unwrap(), 42);
assert_eq!(*scope.get::<String>().unwrap(), "hello");
}
#[test]
fn test_register_value_and_apply() {
let mut list = DiRegistrationList::new();
list.register(100u64);
let scope = SingletonScope::new();
list.apply_to(&scope);
assert_eq!(*scope.get::<u64>().unwrap(), 100);
}
#[test]
fn test_merge() {
let mut list_a = DiRegistrationList::new();
list_a.register_arc(Arc::new(1i32));
let mut list_b = DiRegistrationList::new();
list_b.register_arc(Arc::new("merged".to_string()));
list_a.merge(list_b);
assert_eq!(list_a.len(), 2);
let scope = SingletonScope::new();
list_a.apply_to(&scope);
assert_eq!(*scope.get::<i32>().unwrap(), 1);
assert_eq!(*scope.get::<String>().unwrap(), "merged");
}
#[test]
fn test_apply_empty_is_noop() {
let list = DiRegistrationList::new();
let scope = SingletonScope::new();
list.apply_to(&scope);
assert!(scope.get::<i32>().is_none());
}
}