Skip to main content

di/
type.rs

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