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#[derive(Clone, Debug, Eq)]
9pub struct Type {
10 id: u64,
11 name: String,
12 key: Option<String>,
13}
14
15impl Type {
16 pub fn of<T: ?Sized>() -> Self {
18 Type::new(type_name::<T>().to_string(), None)
19 }
20
21 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 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 pub fn unknown() -> Self {
40 Self::of::<()>()
41 }
42
43 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 pub fn id(&self) -> u64 {
70 self.id
71 }
72
73 pub fn name(&self) -> &str {
75 &self.name
76 }
77
78 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}