Skip to main content

hosting_di/
key.rs

1use std::any::{TypeId, type_name};
2use std::collections::HashMap;
3use std::hash::{BuildHasherDefault, Hash, Hasher};
4
5/// Identity of a service type, carrying its name for diagnostics.
6#[derive(Clone, Copy, Debug)]
7pub(crate) struct Key {
8    pub(crate) id: TypeId,
9    pub(crate) name: &'static str,
10}
11
12impl Key {
13    pub(crate) fn of<T: ?Sized + 'static>() -> Self {
14        Self {
15            id: TypeId::of::<T>(),
16            name: type_name::<T>(),
17        }
18    }
19}
20
21impl PartialEq for Key {
22    fn eq(&self, other: &Self) -> bool {
23        self.id == other.id
24    }
25}
26
27impl Eq for Key {}
28
29impl Hash for Key {
30    fn hash<H: Hasher>(&self, state: &mut H) {
31        self.id.hash(state);
32    }
33}
34
35/// `TypeId` is already a hash, so its `write_u64` is passed through unchanged.
36pub(crate) struct TypeIdHasher(u64);
37
38impl Default for TypeIdHasher {
39    fn default() -> Self {
40        Self(0xcbf2_9ce4_8422_2325)
41    }
42}
43
44impl Hasher for TypeIdHasher {
45    fn finish(&self) -> u64 {
46        self.0
47    }
48
49    fn write(&mut self, bytes: &[u8]) {
50        for &byte in bytes {
51            self.0 ^= u64::from(byte);
52            self.0 = self.0.wrapping_mul(0x0100_0000_01b3);
53        }
54    }
55
56    fn write_u64(&mut self, n: u64) {
57        self.0 = n;
58    }
59}
60
61pub(crate) type KeyMap<V> = HashMap<Key, V, BuildHasherDefault<TypeIdHasher>>;
62
63/// A service another service needs in order to be constructed.
64#[derive(Clone, Copy, Debug, PartialEq, Eq)]
65pub struct Dependency {
66    key: Key,
67    all: bool,
68}
69
70impl Dependency {
71    /// A dependency on a single instance of `T`.
72    pub fn on<T: ?Sized + 'static>() -> Self {
73        Self {
74            key: Key::of::<T>(),
75            all: false,
76        }
77    }
78
79    /// A dependency on every registered implementation of `T`.
80    pub fn all<T: ?Sized + 'static>() -> Self {
81        Self {
82            key: Key::of::<T>(),
83            all: true,
84        }
85    }
86
87    /// The dependency's type name.
88    pub fn type_name(&self) -> &'static str {
89        self.key.name
90    }
91
92    pub(crate) fn key(&self) -> Key {
93        self.key
94    }
95
96    pub(crate) fn is_all(&self) -> bool {
97        self.all
98    }
99}