1use core::{marker::PhantomData, mem::MaybeUninit};
6use cxx::{type_id, ExternType};
7
8#[repr(C)]
15pub struct QHash<T>
16where
17 T: QHashPair,
18{
19 _space: MaybeUninit<usize>,
20 _value: PhantomData<T>,
21}
22
23impl<T> Clone for QHash<T>
24where
25 T: QHashPair,
26{
27 fn clone(&self) -> Self {
29 T::clone(self)
30 }
31}
32
33impl<T> Default for QHash<T>
34where
35 T: QHashPair,
36{
37 fn default() -> Self {
39 T::default()
40 }
41}
42
43impl<T> Drop for QHash<T>
44where
45 T: QHashPair,
46{
47 fn drop(&mut self) {
49 T::drop(self)
50 }
51}
52
53impl<T> PartialEq for QHash<T>
54where
55 T: QHashPair,
56 T::Value: PartialEq,
57{
58 fn eq(&self, other: &Self) -> bool {
59 self.len() == other.len() && self.iter().all(|(k, v)| other.get(k).as_ref() == Some(v))
60 }
61}
62
63impl<T> Eq for QHash<T>
64where
65 T: QHashPair,
66 T::Value: Eq,
67{
68}
69
70impl<T> QHash<T>
71where
72 T: QHashPair,
73{
74 pub fn clear(&mut self) {
76 T::clear(self)
77 }
78
79 pub fn contains(&self, key: &T::Key) -> bool {
81 T::contains(self, key)
82 }
83
84 pub fn get(&self, key: &T::Key) -> Option<T::Value> {
86 if self.contains(key) {
87 Some(T::get_or_default(self, key))
88 } else {
89 None
90 }
91 }
92
93 pub fn get_or_default(&self, key: &T::Key) -> T::Value {
95 T::get_or_default(self, key)
96 }
97
98 pub fn insert_clone(&mut self, key: &T::Key, value: &T::Value) {
103 T::insert_clone(self, key, value)
104 }
105
106 pub fn is_empty(&self) -> bool {
108 T::len(self) == 0
109 }
110
111 pub fn iter(&self) -> Iter<'_, T> {
114 Iter {
115 hash: self,
116 index: 0,
117 }
118 }
119
120 pub fn len(&self) -> isize {
122 T::len(self)
123 }
124
125 pub fn remove(&mut self, key: &T::Key) -> bool {
129 T::remove(self, key)
130 }
131}
132
133impl<T> QHash<T>
134where
135 T: QHashPair,
136 T::Key: ExternType<Kind = cxx::kind::Trivial>,
137 T::Value: ExternType<Kind = cxx::kind::Trivial>,
138{
139 pub fn insert(&mut self, key: T::Key, value: T::Value) {
141 T::insert(self, key, value)
142 }
143}
144
145unsafe impl<T> ExternType for QHash<T>
146where
147 T: QHashPair,
148{
149 type Id = T::TypeId;
150 type Kind = cxx::kind::Trivial;
151}
152
153pub struct Iter<'a, T>
154where
155 T: QHashPair,
156{
157 hash: &'a QHash<T>,
158 index: isize,
159}
160
161impl<'a, T> Iterator for Iter<'a, T>
162where
163 T: QHashPair,
164{
165 type Item = (&'a T::Key, &'a T::Value);
166
167 fn next(&mut self) -> Option<Self::Item> {
168 if self.index < self.hash.len() {
169 let next = unsafe {
170 (
171 T::get_unchecked_key(self.hash, self.index),
172 T::get_unchecked_value(self.hash, self.index),
173 )
174 };
175 self.index += 1;
176 Some(next)
177 } else {
178 None
179 }
180 }
181
182 fn size_hint(&self) -> (usize, Option<usize>) {
183 let len = self.len();
184 (len, Some(len))
185 }
186}
187
188impl<T> ExactSizeIterator for Iter<'_, T>
189where
190 T: QHashPair,
191{
192 fn len(&self) -> usize {
193 (self.hash.len() - self.index) as usize
194 }
195}
196
197pub trait QHashPair: Sized {
199 type Key;
200 type Value;
201 type TypeId;
202
203 fn clear(hash: &mut QHash<Self>);
204 fn clone(hash: &QHash<Self>) -> QHash<Self>;
205 fn contains(hash: &QHash<Self>, key: &Self::Key) -> bool;
206 fn default() -> QHash<Self>;
207 fn drop(hash: &mut QHash<Self>);
208 fn get_or_default(hash: &QHash<Self>, key: &Self::Key) -> Self::Value;
209 unsafe fn get_unchecked_key(hash: &QHash<Self>, pos: isize) -> &Self::Key;
214 unsafe fn get_unchecked_value(hash: &QHash<Self>, pos: isize) -> &Self::Value;
219 fn insert(hash: &mut QHash<Self>, key: Self::Key, value: Self::Value)
220 where
221 Self::Key: ExternType<Kind = cxx::kind::Trivial>,
222 Self::Value: ExternType<Kind = cxx::kind::Trivial>;
223 fn insert_clone(hash: &mut QHash<Self>, key: &Self::Key, value: &Self::Value);
224 fn len(hash: &QHash<Self>) -> isize;
225 fn remove(hash: &mut QHash<Self>, key: &Self::Key) -> bool;
226}
227
228macro_rules! impl_qhash_pair {
229 ( $keyTypeName:ty, $valueTypeName:ty, $module:ident, $pairTypeName:ident, $typeId:literal ) => {
230 mod $module;
231 pub use $module::$pairTypeName;
232
233 impl QHashPair for $module::$pairTypeName {
234 type Key = $keyTypeName;
235 type Value = $valueTypeName;
236 type TypeId = type_id!($typeId);
237
238 fn clear(hash: &mut QHash<Self>) {
239 hash.cxx_clear();
240 }
241
242 fn clone(hash: &QHash<Self>) -> QHash<Self> {
243 $module::clone(hash)
244 }
245
246 fn contains(hash: &QHash<Self>, key: &$keyTypeName) -> bool {
247 hash.cxx_contains(key)
248 }
249
250 fn default() -> QHash<Self> {
251 $module::default()
252 }
253
254 fn drop(hash: &mut QHash<Self>) {
255 $module::drop(hash);
256 }
257
258 fn get_or_default(hash: &QHash<Self>, key: &$keyTypeName) -> $valueTypeName {
259 $module::get_or_default(hash, key)
260 }
261
262 unsafe fn get_unchecked_key(hash: &QHash<Self>, pos: isize) -> &$keyTypeName {
263 $module::get_unchecked_key(hash, pos)
264 }
265
266 unsafe fn get_unchecked_value(hash: &QHash<Self>, pos: isize) -> &$valueTypeName {
267 $module::get_unchecked_value(hash, pos)
268 }
269
270 fn insert(hash: &mut QHash<Self>, key: $keyTypeName, value: $valueTypeName) {
271 $module::insert(hash, &key, &value);
272 }
273
274 fn insert_clone(hash: &mut QHash<Self>, key: &$keyTypeName, value: &$valueTypeName) {
275 $module::insert(hash, key, value);
276 }
277
278 fn len(hash: &QHash<Self>) -> isize {
279 $module::len(hash)
280 }
281
282 fn remove(hash: &mut QHash<Self>, key: &$keyTypeName) -> bool {
283 $module::remove(hash, key)
284 }
285 }
286 };
287}
288
289impl_qhash_pair!(
295 crate::QString,
296 crate::QVariant,
297 qhash_qstring_qvariant,
298 QHashPair_QString_QVariant,
299 "QHash_QString_QVariant"
300);
301impl_qhash_pair!(
303 i32,
304 crate::QByteArray,
305 qhash_i32_qbytearray,
306 QHashPair_i32_QByteArray,
307 "QHash_i32_QByteArray"
308);