ferroui_base/controls/
resource_key.rs1use crate::TypeInfo;
2use std::any::Any;
3use std::fmt;
4use std::hash::{BuildHasherDefault, Hash, Hasher};
5use std::rc::Rc;
6
7pub trait ResourceKeyObject: Any {
11 fn as_any(&self) -> &dyn Any;
12 fn dyn_eq(&self, other: &dyn ResourceKeyObject) -> bool;
13 fn dyn_hash(&self, state: &mut dyn Hasher);
14 fn key_type_name(&self) -> &'static str;
15}
16
17impl<T: Eq + Hash + 'static> ResourceKeyObject for T {
18 fn as_any(&self) -> &dyn Any {
19 self
20 }
21
22 fn dyn_eq(&self, other: &dyn ResourceKeyObject) -> bool {
23 other.as_any().downcast_ref::<T>().is_some_and(|other| self == other)
24 }
25
26 fn dyn_hash(&self, mut state: &mut dyn Hasher) {
27 self.hash(&mut state)
28 }
29
30 fn key_type_name(&self) -> &'static str {
31 std::any::type_name::<T>()
32 }
33}
34
35#[derive(Clone)]
43pub enum ResourceKey {
44 String(Rc<str>),
46 Type(&'static TypeInfo),
48 Object(Rc<dyn ResourceKeyObject>),
50}
51
52impl ResourceKey {
53 pub fn object<T: Eq + Hash + 'static>(value: T) -> Self {
55 ResourceKey::Object(Rc::new(value))
56 }
57
58 pub fn as_str(&self) -> Option<&str> {
60 match self {
61 ResourceKey::String(s) => Some(s),
62 _ => None,
63 }
64 }
65}
66
67impl PartialEq for ResourceKey {
68 fn eq(&self, other: &Self) -> bool {
69 match (self, other) {
70 (ResourceKey::String(a), ResourceKey::String(b)) => a == b,
71 (ResourceKey::Type(a), ResourceKey::Type(b)) => std::ptr::eq(*a, *b),
72 (ResourceKey::Object(a), ResourceKey::Object(b)) => (**a).dyn_eq(&**b),
73 _ => false,
74 }
75 }
76}
77
78impl Eq for ResourceKey {}
79
80impl Hash for ResourceKey {
81 fn hash<H: Hasher>(&self, state: &mut H) {
82 match self {
83 ResourceKey::String(s) => {
84 state.write_u8(0);
85 s.hash(state)
86 }
87 ResourceKey::Type(t) => {
88 state.write_u8(1);
89 t.hash(state)
90 }
91 ResourceKey::Object(o) => {
92 state.write_u8(2);
93 (**o).dyn_hash(state)
94 }
95 }
96 }
97}
98
99impl fmt::Debug for ResourceKey {
100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 fmt::Display::fmt(self, f)
102 }
103}
104
105impl fmt::Display for ResourceKey {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 match self {
108 ResourceKey::String(s) => f.write_str(s),
109 ResourceKey::Type(t) => f.write_str(t.name()),
110 ResourceKey::Object(o) => f.write_str((**o).key_type_name()),
111 }
112 }
113}
114
115impl From<&str> for ResourceKey {
116 fn from(value: &str) -> Self {
117 ResourceKey::String(value.into())
118 }
119}
120
121impl From<String> for ResourceKey {
122 fn from(value: String) -> Self {
123 ResourceKey::String(value.into())
124 }
125}
126
127impl From<&'static TypeInfo> for ResourceKey {
128 fn from(value: &'static TypeInfo) -> Self {
129 ResourceKey::Type(value)
130 }
131}
132
133impl From<&ResourceKey> for ResourceKey {
134 fn from(value: &ResourceKey) -> Self {
135 value.clone()
136 }
137}
138
139#[derive(Clone, Copy, Default)]
152pub(crate) struct ResourceKeyHasher {
153 hash: u64,
154}
155
156pub(crate) type ResourceKeyBuildHasher = BuildHasherDefault<ResourceKeyHasher>;
158
159impl ResourceKeyHasher {
160 const MULTIPLIER: u64 = 0x51_7c_c1_b7_27_22_0a_95;
161
162 #[inline]
163 fn add(&mut self, word: u64) {
164 let product = (self.hash ^ word).wrapping_mul(Self::MULTIPLIER);
165 self.hash = product ^ (product >> 32);
166 }
167}
168
169impl Hasher for ResourceKeyHasher {
170 #[inline]
171 fn finish(&self) -> u64 {
172 self.hash
173 }
174
175 #[inline]
176 fn write(&mut self, bytes: &[u8]) {
177 let mut chunks = bytes.chunks_exact(8);
178 for chunk in &mut chunks {
179 let mut word = [0u8; 8];
180 word.copy_from_slice(chunk);
181 self.add(u64::from_le_bytes(word));
182 }
183 let rest = chunks.remainder();
184 if !rest.is_empty() {
185 let mut word = [0u8; 8];
188 word[..rest.len()].copy_from_slice(rest);
189 word[7] = rest.len() as u8;
190 self.add(u64::from_le_bytes(word));
191 }
192 }
193
194 #[inline]
195 fn write_u8(&mut self, i: u8) {
196 self.add(u64::from(i));
197 }
198
199 #[inline]
200 fn write_u16(&mut self, i: u16) {
201 self.add(u64::from(i));
202 }
203
204 #[inline]
205 fn write_u32(&mut self, i: u32) {
206 self.add(u64::from(i));
207 }
208
209 #[inline]
210 fn write_u64(&mut self, i: u64) {
211 self.add(i);
212 }
213
214 #[inline]
215 fn write_usize(&mut self, i: usize) {
216 self.add(i as u64);
217 }
218}