1use std::{
2 any::{type_name, TypeId},
3 fmt::Debug,
4 hash::{BuildHasher, Hasher},
5 marker::PhantomData,
6 sync::OnceLock,
7};
8
9use bones_utils::{default, HashMap};
10use hashbrown::hash_map;
11use parking_lot::RwLock;
12
13use crate::{
14 prelude::*,
15 raw_fns::{RawClone, RawDefault, RawDrop},
16};
17
18#[derive(Clone, Debug)]
20pub struct SchemaMap {
21 map: HashMap<SchemaBox, SchemaBox>,
22 key_schema: &'static Schema,
23 value_schema: &'static Schema,
24}
25
26impl SchemaMap {
27 pub fn new(key_schema: &'static Schema, value_schema: &'static Schema) -> Self {
29 assert!(
30 key_schema.hash_fn.is_some() && key_schema.eq_fn.is_some(),
31 "Key schema must implement hash and eq"
32 );
33 Self {
34 map: HashMap::default(),
35 key_schema,
36 value_schema,
37 }
38 }
39
40 #[inline]
42 pub fn len(&self) -> usize {
43 self.map.len()
44 }
45
46 #[inline]
48 pub fn is_empty(&self) -> bool {
49 self.map.is_empty()
50 }
51
52 pub fn key_schema(&self) -> &'static Schema {
54 self.key_schema
55 }
56
57 pub fn value_schema(&self) -> &'static Schema {
59 self.value_schema
60 }
61
62 #[inline]
66 #[track_caller]
67 pub fn insert<K: HasSchema, V: HasSchema>(&mut self, key: K, value: V) -> Option<V> {
68 self.try_insert(key, value).unwrap()
69 }
70
71 pub fn try_insert<K: HasSchema, V: HasSchema>(
75 &mut self,
76 key: K,
77 value: V,
78 ) -> Result<Option<V>, SchemaMismatchError> {
79 let key = SchemaBox::new(key);
80 let value = SchemaBox::new(value);
81 self.try_insert_box(key, value)
82 .map(|value| value.map(|x| unsafe { x.cast_into_unchecked() }))
85 }
86
87 #[track_caller]
91 #[inline]
92 pub fn insert_box(&mut self, key: SchemaBox, value: SchemaBox) -> Option<SchemaBox> {
93 self.try_insert_box(key, value).unwrap()
94 }
95
96 pub fn try_insert_box(
100 &mut self,
101 key: SchemaBox,
102 value: SchemaBox,
103 ) -> Result<Option<SchemaBox>, SchemaMismatchError> {
104 if key.schema() != self.key_schema || value.schema() != self.value_schema {
105 Err(SchemaMismatchError)
106 } else {
107 let previous_value = unsafe { self.insert_box_unchecked(key, value) };
109 Ok(previous_value)
110 }
111 }
112
113 pub unsafe fn insert_box_unchecked(
116 &mut self,
117 key: SchemaBox,
118 mut value: SchemaBox,
119 ) -> Option<SchemaBox> {
120 let hash = {
121 let mut hasher = self.map.hasher().build_hasher();
122 hasher.write_u64(key.hash());
123 hasher.finish()
124 };
125 let entry = self
126 .map
127 .raw_entry_mut()
128 .from_hash(hash, |other| other == &key);
129 match entry {
131 hash_map::RawEntryMut::Occupied(mut occupied) => {
132 std::mem::swap(occupied.get_mut(), &mut value);
133 Some(value)
134 }
135 hash_map::RawEntryMut::Vacant(vacant) => {
136 vacant.insert(key, value);
137 None
138 }
139 }
140 }
141
142 #[track_caller]
146 #[inline]
147 pub fn get<K: HasSchema, V: HasSchema>(&self, key: &K) -> Option<&V> {
148 self.try_get(key).unwrap()
149 }
150
151 #[track_caller]
155 pub fn try_get<K: HasSchema, V: HasSchema>(
156 &self,
157 key: &K,
158 ) -> Result<Option<&V>, SchemaMismatchError> {
159 if K::schema() != self.key_schema || V::schema() != self.value_schema {
160 Err(SchemaMismatchError)
161 } else {
162 let value = unsafe { self.get_ref_unchecked(SchemaRef::new(key)) }
164 .map(|x| unsafe { x.cast_into_unchecked() });
166
167 Ok(value)
168 }
169 }
170
171 #[inline]
175 #[track_caller]
176 pub fn get_ref(&self, key: SchemaRef) -> Option<SchemaRef<'_>> {
177 self.try_get_ref(key).unwrap()
178 }
179
180 pub fn try_get_ref(
184 &self,
185 key: SchemaRef,
186 ) -> Result<Option<SchemaRef<'_>>, SchemaMismatchError> {
187 if key.schema() != self.key_schema {
188 Err(SchemaMismatchError)
189 } else {
190 Ok(unsafe { self.get_ref_unchecked(key) })
192 }
193 }
194
195 pub unsafe fn get_ref_unchecked(&self, key: SchemaRef) -> Option<SchemaRef<'_>> {
198 let Some(hash_fn) = &self.key_schema.hash_fn else {
199 panic!("Key schema doesn't implement hash");
200 };
201 let Some(eq_fn) = &self.key_schema.eq_fn else {
202 panic!("Key schema doesn't implement eq");
203 };
204 let key_ptr = key.as_ptr();
205 let raw_hash = unsafe { (hash_fn.get())(key_ptr) };
207 let hash = {
208 let mut hasher = self.map.hasher().build_hasher();
209 hasher.write_u64(raw_hash);
210 hasher.finish()
211 };
212 self.map
213 .raw_entry()
214 .from_hash(hash, |key| {
215 let other_ptr = key.as_ref().as_ptr();
216 unsafe { (eq_fn.get())(key_ptr, other_ptr) }
218 })
219 .map(|x| x.1.as_ref())
220 }
221
222 #[inline]
226 #[track_caller]
227 pub fn get_ref_mut(&mut self, key: SchemaRef) -> Option<SchemaRefMut<'_>> {
228 self.try_get_ref_mut(key).unwrap()
229 }
230
231 pub fn try_get_ref_mut(
235 &mut self,
236 key: SchemaRef,
237 ) -> Result<Option<SchemaRefMut<'_>>, SchemaMismatchError> {
238 if key.schema() != self.key_schema {
239 Err(SchemaMismatchError)
240 } else {
241 Ok(unsafe { self.get_ref_unchecked_mut(key) })
243 }
244 }
245
246 pub unsafe fn get_ref_unchecked_mut(&mut self, key: SchemaRef) -> Option<SchemaRefMut<'_>> {
249 let Some(hash_fn) = &self.key_schema.hash_fn else {
250 panic!("Key schema doesn't implement hash");
251 };
252 let Some(eq_fn) = &self.key_schema.eq_fn else {
253 panic!("Key schema doesn't implement eq");
254 };
255 let key_ptr = key.as_ptr();
256 let raw_hash = unsafe { (hash_fn.get())(key_ptr) };
258 let hash = {
259 let mut hasher = self.map.hasher().build_hasher();
260 hasher.write_u64(raw_hash);
261 hasher.finish()
262 };
263 let entry = self.map.raw_entry_mut().from_hash(hash, |key| {
264 let other_ptr = key.as_ref().as_ptr();
265 unsafe { (eq_fn.get())(key_ptr, other_ptr) }
267 });
268 match entry {
269 hash_map::RawEntryMut::Occupied(entry) => Some(entry.into_mut()),
270 hash_map::RawEntryMut::Vacant(_) => None,
271 }
272 .map(|x| x.as_mut())
273 }
274
275 #[track_caller]
279 #[inline]
280 pub fn get_mut<K: HasSchema, V: HasSchema>(&mut self, key: &K) -> Option<&mut V> {
281 self.try_get_mut(key).unwrap()
282 }
283
284 #[track_caller]
288 pub fn try_get_mut<K: HasSchema, V: HasSchema>(
289 &mut self,
290 key: &K,
291 ) -> Result<Option<&mut V>, SchemaMismatchError> {
292 if K::schema() != self.key_schema || V::schema() != self.value_schema {
293 Err(SchemaMismatchError)
294 } else {
295 let value = unsafe { self.get_ref_unchecked_mut(SchemaRef::new(key)) }
297 .map(|x| unsafe { x.cast_into_mut_unchecked() });
299 Ok(value)
300 }
301 }
302
303 #[inline]
307 #[track_caller]
308 pub fn remove<K: HasSchema, V: HasSchema>(&mut self, key: &K) -> Option<V> {
309 self.try_remove(key).unwrap()
310 }
311
312 pub fn try_remove<K: HasSchema, V: HasSchema>(
316 &mut self,
317 key: &K,
318 ) -> Result<Option<V>, SchemaMismatchError> {
319 if K::schema() != self.key_schema || V::schema() != self.value_schema {
320 Err(SchemaMismatchError)
321 } else {
322 let value = unsafe { self.remove_unchecked(SchemaRef::new(key)) }
324 .map(|x| unsafe { x.cast_into_unchecked() });
326 Ok(value)
327 }
328 }
329
330 #[inline]
334 #[track_caller]
335 pub fn remove_box(&mut self, key: SchemaRef) -> Option<SchemaBox> {
336 self.try_remove_box(key).unwrap()
337 }
338
339 pub fn try_remove_box(
343 &mut self,
344 key: SchemaRef,
345 ) -> Result<Option<SchemaBox>, SchemaMismatchError> {
346 if key.schema() != self.key_schema {
347 Err(SchemaMismatchError)
348 } else {
349 Ok(unsafe { self.remove_unchecked(key) })
351 }
352 }
353
354 pub unsafe fn remove_unchecked(&mut self, key: SchemaRef) -> Option<SchemaBox> {
357 let Some(hash_fn) = &self.key_schema.hash_fn else {
358 panic!("Key schema doesn't implement hash");
359 };
360 let Some(eq_fn) = &self.key_schema.eq_fn else {
361 panic!("Key schema doesn't implement eq");
362 };
363 let key_ptr = key.as_ptr();
364 let hash = unsafe { (hash_fn.get())(key_ptr) };
366 let hash = {
367 let mut hasher = self.map.hasher().build_hasher();
368 hasher.write_u64(hash);
369 hasher.finish()
370 };
371 let entry = self.map.raw_entry_mut().from_hash(hash, |key| {
372 let other_ptr = key.as_ref().as_ptr();
373 unsafe { (eq_fn.get())(key_ptr, other_ptr) }
375 });
376 match entry {
377 hash_map::RawEntryMut::Occupied(entry) => Some(entry.remove()),
378 hash_map::RawEntryMut::Vacant(_) => None,
379 }
380 }
381
382 #[inline]
386 #[track_caller]
387 pub fn into_smap<K: HasSchema, V: HasSchema>(self) -> SMap<K, V> {
388 self.try_into_smap().unwrap()
389 }
390
391 pub fn try_into_smap<K: HasSchema, V: HasSchema>(
395 self,
396 ) -> Result<SMap<K, V>, SchemaMismatchError> {
397 if K::schema() == self.key_schema && V::schema() == self.value_schema {
398 Ok(SMap {
399 map: self,
400 _phantom: PhantomData,
401 })
402 } else {
403 Err(SchemaMismatchError)
404 }
405 }
406}
407
408impl<K: HasSchema, V: HasSchema> FromIterator<(K, V)> for SMap<K, V> {
409 fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
410 let mut this = Self::default();
411 for (k, v) in iter {
412 this.insert(k, v);
413 }
414 this
415 }
416}
417
418impl<K: HasSchema, V: HasSchema> std::ops::Index<&K> for SMap<K, V> {
419 type Output = V;
420 fn index(&self, index: &K) -> &Self::Output {
421 self.get(index).unwrap()
422 }
423}
424impl<K: HasSchema, V: HasSchema> std::ops::IndexMut<&K> for SMap<K, V> {
425 fn index_mut(&mut self, index: &K) -> &mut Self::Output {
426 self.get_mut(index).unwrap()
427 }
428}
429
430type SchemaMapIter<'iter> = std::iter::Map<
431 hash_map::Iter<'iter, SchemaBox, SchemaBox>,
432 for<'a> fn((&'a SchemaBox, &'a SchemaBox)) -> (SchemaRef<'a>, SchemaRef<'a>),
433>;
434type SchemaMapIterMut<'iter> = std::iter::Map<
435 hash_map::IterMut<'iter, SchemaBox, SchemaBox>,
436 for<'a> fn((&'a SchemaBox, &'a mut SchemaBox)) -> (SchemaRef<'a>, SchemaRefMut<'a>),
437>;
438impl SchemaMap {
439 #[allow(clippy::type_complexity)]
441 pub fn iter(&self) -> SchemaMapIter<'_> {
442 fn map_fn<'a>(
443 (key, value): (&'a SchemaBox, &'a SchemaBox),
444 ) -> (SchemaRef<'a>, SchemaRef<'a>) {
445 (key.as_ref(), value.as_ref())
446 }
447 self.map.iter().map(map_fn)
448 }
449
450 #[allow(clippy::type_complexity)]
452 pub fn iter_mut(&mut self) -> SchemaMapIterMut<'_> {
453 fn map_fn<'a>(
454 (key, value): (&'a SchemaBox, &'a mut SchemaBox),
455 ) -> (SchemaRef<'a>, SchemaRefMut<'a>) {
456 (key.as_ref(), value.as_mut())
457 }
458 self.map.iter_mut().map(map_fn)
459 }
460
461 #[allow(clippy::type_complexity)]
463 pub fn keys(
464 &self,
465 ) -> std::iter::Map<
466 hash_map::Keys<'_, SchemaBox, SchemaBox>,
467 for<'a> fn(&'a SchemaBox) -> SchemaRef<'a>,
468 > {
469 fn map_fn(key: &SchemaBox) -> SchemaRef<'_> {
470 key.as_ref()
471 }
472 self.map.keys().map(map_fn)
473 }
474
475 #[allow(clippy::type_complexity)]
477 pub fn values(
478 &self,
479 ) -> std::iter::Map<
480 hash_map::Values<'_, SchemaBox, SchemaBox>,
481 for<'a> fn(&'a SchemaBox) -> SchemaRef<'a>,
482 > {
483 fn map_fn(key: &SchemaBox) -> SchemaRef<'_> {
484 key.as_ref()
485 }
486 self.map.values().map(map_fn)
487 }
488
489 #[allow(clippy::type_complexity)]
491 pub fn values_mut(
492 &mut self,
493 ) -> std::iter::Map<
494 hash_map::ValuesMut<'_, SchemaBox, SchemaBox>,
495 for<'a> fn(&'a mut SchemaBox) -> SchemaRefMut<'a>,
496 > {
497 fn map_fn(key: &mut SchemaBox) -> SchemaRefMut<'_> {
498 key.as_mut()
499 }
500 self.map.values_mut().map(map_fn)
501 }
502}
503impl<'a> IntoIterator for &'a SchemaMap {
504 type Item = (SchemaRef<'a>, SchemaRef<'a>);
505 type IntoIter = SchemaMapIter<'a>;
506 fn into_iter(self) -> Self::IntoIter {
507 self.iter()
508 }
509}
510impl<'a> IntoIterator for &'a mut SchemaMap {
511 type Item = (SchemaRef<'a>, SchemaRefMut<'a>);
512 type IntoIter = SchemaMapIterMut<'a>;
513 fn into_iter(self) -> Self::IntoIter {
514 self.iter_mut()
515 }
516}
517
518pub struct SMap<K: HasSchema, V: HasSchema> {
525 map: SchemaMap,
526 _phantom: PhantomData<(K, V)>,
527}
528impl<K: HasSchema + Debug, V: HasSchema + Debug> Debug for SMap<K, V> {
529 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
530 let mut f = f.debug_map();
531 for (k, v) in self {
532 f.entry(k, v);
533 }
534 f.finish()
535 }
536}
537impl<K: HasSchema, V: HasSchema> Clone for SMap<K, V> {
538 fn clone(&self) -> Self {
539 Self {
540 map: self.map.clone(),
541 _phantom: self._phantom,
542 }
543 }
544}
545impl<K: HasSchema, V: HasSchema> Default for SMap<K, V> {
546 fn default() -> Self {
547 Self {
548 map: SchemaMap::new(K::schema(), V::schema()),
549 _phantom: Default::default(),
550 }
551 }
552}
553unsafe impl<K: HasSchema, V: HasSchema> HasSchema for SMap<K, V> {
554 fn schema() -> &'static Schema {
555 static S: OnceLock<RwLock<HashMap<TypeId, &'static Schema>>> = OnceLock::new();
556 let schema = {
557 S.get_or_init(default)
558 .read()
559 .get(&TypeId::of::<Self>())
560 .copied()
561 };
562 schema.unwrap_or_else(|| {
563 let schema = SCHEMA_REGISTRY.register(SchemaData {
564 name: type_name::<Self>().into(),
565 full_name: format!("{}::{}", module_path!(), type_name::<Self>()).into(),
566 kind: SchemaKind::Map {
567 key: K::schema(),
568 value: V::schema(),
569 },
570 type_id: Some(TypeId::of::<Self>()),
571 clone_fn: Some(<Self as RawClone>::raw_clone_cb()),
572 drop_fn: Some(<Self as RawDrop>::raw_drop_cb()),
573 default_fn: Some(<Self as RawDefault>::raw_default_cb()),
574 hash_fn: Some(unsafe {
575 Unsafe::new(Box::leak(Box::new(|a| SchemaVec::raw_hash(a))))
576 }),
577 eq_fn: Some(unsafe {
578 Unsafe::new(Box::leak(Box::new(|a, b| SchemaVec::raw_eq(a, b))))
579 }),
580 type_data: Default::default(),
581 });
582
583 S.get_or_init(default)
584 .write()
585 .insert(TypeId::of::<Self>(), schema);
586
587 schema
588 })
589 }
590}
591
592impl<K: HasSchema, V: HasSchema> SMap<K, V> {
593 pub fn new() -> Self {
595 Self::default()
596 }
597
598 pub fn insert(&mut self, k: K, v: V) -> Option<V> {
600 unsafe {
602 self.map
603 .insert_box_unchecked(SchemaBox::new(k), SchemaBox::new(v))
604 .map(|x| x.cast_into_unchecked())
605 }
606 }
607
608 pub fn get(&self, key: &K) -> Option<&V> {
610 unsafe {
612 self.map
613 .get_ref_unchecked(SchemaRef::new(key))
614 .map(|x| x.cast_into_unchecked())
615 }
616 }
617
618 pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
620 unsafe {
622 self.map
623 .get_ref_unchecked_mut(SchemaRef::new(key))
624 .map(|x| x.cast_into_mut_unchecked())
625 }
626 }
627
628 pub fn remove(&mut self, key: &K) -> Option<V> {
630 unsafe {
632 self.map
633 .remove_unchecked(SchemaRef::new(key))
634 .map(|x| x.cast_into_unchecked())
635 }
636 }
637
638 pub fn into_schema_map(self) -> SchemaMap {
640 self.map
641 }
642
643 pub fn contains_key(&self, key: &K) -> bool {
645 self.map.get::<K, V>(key).is_some()
646 }
647
648 pub fn len(&self) -> usize {
650 self.map.len()
651 }
652
653 pub fn is_empty(&self) -> bool {
655 self.map.is_empty()
656 }
657}
658
659type SMapIter<'iter, K, V> = std::iter::Map<
660 hash_map::Iter<'iter, SchemaBox, SchemaBox>,
661 for<'a> fn((&'a SchemaBox, &'a SchemaBox)) -> (&'a K, &'a V),
662>;
663type SMapIterMut<'iter, K, V> = std::iter::Map<
664 hash_map::IterMut<'iter, SchemaBox, SchemaBox>,
665 for<'a> fn((&'a SchemaBox, &'a mut SchemaBox)) -> (&'a K, &'a mut V),
666>;
667impl<K: HasSchema, V: HasSchema> SMap<K, V> {
668 #[allow(clippy::type_complexity)]
670 pub fn iter(&self) -> SMapIter<'_, K, V> {
671 fn map_fn<'a, K: HasSchema, V: HasSchema>(
672 (key, value): (&'a SchemaBox, &'a SchemaBox),
673 ) -> (&'a K, &'a V) {
674 unsafe {
676 (
677 key.as_ref().cast_into_unchecked(),
678 value.as_ref().cast_into_unchecked(),
679 )
680 }
681 }
682 self.map.map.iter().map(map_fn)
683 }
684
685 #[allow(clippy::type_complexity)]
687 pub fn iter_mut(&mut self) -> SMapIterMut<'_, K, V> {
688 fn map_fn<'a, K: HasSchema, V: HasSchema>(
689 (key, value): (&'a SchemaBox, &'a mut SchemaBox),
690 ) -> (&'a K, &'a mut V) {
691 unsafe {
693 (
694 key.as_ref().cast_into_unchecked(),
695 value.as_mut().cast_into_mut_unchecked(),
696 )
697 }
698 }
699 self.map.map.iter_mut().map(map_fn)
700 }
701
702 #[allow(clippy::type_complexity)]
704 pub fn keys(
705 &self,
706 ) -> std::iter::Map<hash_map::Keys<'_, SchemaBox, SchemaBox>, for<'a> fn(&'a SchemaBox) -> &'a K>
707 {
708 fn map_fn<K: HasSchema>(key: &SchemaBox) -> &K {
709 unsafe { key.as_ref().cast_into_unchecked() }
711 }
712 self.map.map.keys().map(map_fn)
713 }
714
715 #[allow(clippy::type_complexity)]
717 pub fn values(
718 &self,
719 ) -> std::iter::Map<
720 hash_map::Values<'_, SchemaBox, SchemaBox>,
721 for<'a> fn(&'a SchemaBox) -> &'a V,
722 > {
723 fn map_fn<V: HasSchema>(value: &SchemaBox) -> &V {
724 unsafe { value.as_ref().cast_into_unchecked() }
726 }
727 self.map.map.values().map(map_fn)
728 }
729
730 #[allow(clippy::type_complexity)]
732 pub fn values_mut(
733 &mut self,
734 ) -> std::iter::Map<
735 hash_map::ValuesMut<'_, SchemaBox, SchemaBox>,
736 for<'a> fn(&'a mut SchemaBox) -> &'a mut V,
737 > {
738 fn map_fn<V>(value: &mut SchemaBox) -> &mut V {
739 unsafe { value.as_mut().cast_into_mut_unchecked() }
741 }
742 self.map.map.values_mut().map(map_fn)
743 }
744}
745impl<'a, K: HasSchema, V: HasSchema> IntoIterator for &'a SMap<K, V> {
746 type Item = (&'a K, &'a V);
747 type IntoIter = SMapIter<'a, K, V>;
748 fn into_iter(self) -> Self::IntoIter {
749 self.iter()
750 }
751}
752impl<'a, K: HasSchema, V: HasSchema> IntoIterator for &'a mut SMap<K, V> {
753 type Item = (&'a K, &'a mut V);
754 type IntoIter = SMapIterMut<'a, K, V>;
755 fn into_iter(self) -> Self::IntoIter {
756 self.iter_mut()
757 }
758}