di/
type.rs

1use crate::{ServiceProvider, Ref};
2use std::any::type_name;
3use std::collections::hash_map::DefaultHasher;
4use std::fmt::{Display, Formatter, Result as FormatResult};
5use std::hash::{Hash, Hasher};
6
7/// Represents a type.
8#[derive(Clone, Debug, Eq)]
9pub struct Type {
10    id: u64,
11    name: String,
12    key: Option<String>,
13}
14
15impl Type {
16    /// Initializes a new instance of a type.
17    pub fn of<T: ?Sized>() -> Self {
18        Type::new(type_name::<T>().to_string(), None)
19    }
20
21    /// Initializes a new instance of a type based on another type as a key.
22    pub fn keyed<TKey, TType: ?Sized>() -> Self {
23        Type::new(
24            type_name::<TType>().to_string(),
25            Some(type_name::<TKey>().to_string()),
26        )
27    }
28
29    /// Initializes a new instance of a type for a factory function based
30    /// on the specified return type.
31    pub fn factory_of<TSvc: ?Sized>() -> Self {
32        Type::new(
33            type_name::<dyn Fn(&ServiceProvider) -> Ref<TSvc>>().to_string(),
34            None,
35        )
36    }
37
38    /// Initializes a new instance for an unknown type.
39    pub fn unknown() -> Self {
40        Self::of::<()>()
41    }
42
43    /// Creates and returns a new type based on the specified key.
44    ///
45    /// # Arguments
46    ///
47    /// * `key` - The type to use as a key
48    pub fn with_key(&self, key: &Self) -> Self {
49        Type::new(self.name.clone(), Some(key.name.clone()))
50    }
51
52    fn new(name: String, key: Option<String>) -> Self {
53        let mut hasher = DefaultHasher::new();
54
55        name.hash(&mut hasher);
56
57        if let Some(ref val) = key {
58            val.hash(&mut hasher);
59        }
60
61        Self {
62            id: hasher.finish(),
63            name,
64            key,
65        }
66    }
67
68    /// Gets the type identifier.
69    pub fn id(&self) -> u64 {
70        self.id
71    }
72
73    /// Gets the type name.
74    pub fn name(&self) -> &str {
75        &self.name
76    }
77
78    /// Deconstructs the specified type into its name component
79    /// and key component, if it is defined.
80    pub fn deconstruct(t: &Type) -> (&str, Option<&str>) {
81        (&t.name, t.key.as_deref())
82    }
83}
84
85impl PartialEq<Type> for Type {
86    fn eq(&self, other: &Self) -> bool {
87        self.id == other.id
88    }
89}
90
91impl PartialEq<Type> for &Type {
92    fn eq(&self, other: &Type) -> bool {
93        self.id == other.id
94    }
95}
96
97impl Hash for Type {
98    fn hash<H: Hasher>(&self, state: &mut H) {
99        self.id.hash(state);
100    }
101}
102
103impl Display for Type {
104    fn fmt(&self, formatter: &mut Formatter<'_>) -> FormatResult {
105        formatter.write_str(&self.name)
106    }
107}