1use std::alloc::{alloc, dealloc, Layout, LayoutError};
4use std::cmp::{self, Ordering};
5use std::collections::hash_map::DefaultHasher;
6use std::collections::{BTreeMap, HashMap};
7use std::fmt::{self, Debug, Formatter};
8use std::hash::{Hash, Hasher};
9use std::iter::FromIterator;
10use std::mem;
11use std::ops::{Index, IndexMut};
12
13#[cfg(feature = "indexmap")]
14use indexmap::IndexMap;
15
16use crate::thin::{ThinMut, ThinMutExt, ThinRef, ThinRefExt};
17
18use super::string::IString;
19use super::value::{IValue, TypeTag};
20
21#[repr(C)]
22#[repr(align(4))]
23struct Header {
24 len: usize,
25 cap: usize,
26}
27
28#[repr(C)]
29#[derive(Debug)]
30struct KeyValuePair {
31 key: IString,
32 value: IValue,
33}
34
35fn hash_capacity(cap: usize) -> usize {
36 cap + cap / 4
37}
38
39fn hash_fn(s: &IString) -> usize {
40 let v: &IValue = s.as_ref();
41 let mut p = v.ptr_usize() >> 2;
43 p = p.wrapping_mul(202_529);
44 p = p ^ (p >> 13);
45 p.wrapping_mul(202_529)
46}
47
48fn hash_bucket(s: &IString, hash_cap: usize) -> usize {
49 hash_fn(s) % hash_cap
50}
51
52struct SplitHeader<'a> {
53 cap: usize,
54 items: &'a [KeyValuePair],
55 table: &'a [usize],
56}
57
58impl<'a> SplitHeader<'a> {
59 fn find_bucket(&self, key: &IString) -> Result<usize, usize> {
60 let hash_cap = hash_capacity(self.cap);
61 let initial_bucket = hash_bucket(key, hash_cap);
62 unsafe {
63 for i in 0..hash_cap {
65 let bucket = (initial_bucket + i) % hash_cap;
66 let index = *self.table.get_unchecked(bucket);
67
68 if index == usize::MAX {
70 return Err(bucket);
71 }
72
73 let k = &self.items.get_unchecked(index).key;
75 if k == key {
76 return Ok(bucket);
77 }
78
79 let key_dist = (bucket + hash_cap - hash_bucket(k, hash_cap)) % hash_cap;
82 if key_dist < i {
83 return Err(bucket);
84 }
85 }
86 }
87 Err(usize::MAX)
88 }
89 unsafe fn find_bucket_from_index(&self, index: usize) -> usize {
91 let hash_cap = hash_capacity(self.cap);
92 let key = &self.items.get_unchecked(index).key;
93 let mut bucket = hash_bucket(key, hash_cap);
94
95 while *self.table.get_unchecked(bucket) != index {
98 bucket = (bucket + 1) % hash_cap;
99 }
100
101 bucket
102 }
103}
104
105struct SplitHeaderMut<'a> {
106 cap: usize,
107 items: &'a mut [KeyValuePair],
108 table: &'a mut [usize],
109}
110
111impl<'a> SplitHeaderMut<'a> {
112 fn as_ref(&self) -> SplitHeader {
113 SplitHeader {
114 cap: self.cap,
115 items: self.items,
116 table: self.table,
117 }
118 }
119 unsafe fn unshift(&mut self, initial_bucket: usize) {
123 let hash_cap = hash_capacity(self.cap);
124 let mut prev_bucket = initial_bucket;
125 for i in 1..hash_cap {
126 let bucket = (initial_bucket + i) % hash_cap;
127 let index = *self.table.get_unchecked(bucket);
128
129 if index == usize::MAX {
131 return;
132 }
133
134 let k = &self.items.get_unchecked(index).key;
136 if hash_bucket(k, hash_cap) == bucket {
137 return;
138 }
139
140 self.table.swap(prev_bucket, bucket);
142 prev_bucket = bucket;
143 }
144 }
145 unsafe fn shift(&mut self, initial_bucket: usize, mut index: usize) {
151 let hash_cap = hash_capacity(self.cap);
152 for i in 0..hash_cap {
153 if index == usize::MAX {
155 return;
156 }
157
158 let bucket = (initial_bucket + i) % hash_cap;
159 mem::swap(self.table.get_unchecked_mut(bucket), &mut index);
160 }
161 }
162 unsafe fn remove_bucket(&mut self, bucket: usize) {
164 let index = mem::replace(self.table.get_unchecked_mut(bucket), usize::MAX);
166
167 self.unshift(bucket);
169
170 let last_index = self.items.len() - 1;
173 if last_index != index {
174 let bucket_to_update = self.as_ref().find_bucket_from_index(last_index);
176
177 *self.table.get_unchecked_mut(bucket_to_update) = index;
180
181 self.items.swap(index, last_index);
183 }
184 }
185}
186
187trait HeaderRef<'a>: ThinRefExt<'a, Header> {
188 fn items_ptr(&self) -> *const KeyValuePair {
189 unsafe { self.ptr().add(1).cast() }
191 }
192 fn hashes_ptr(&self) -> *const usize {
193 unsafe { self.items_ptr().add(self.cap).cast() }
195 }
196 fn split(&self) -> SplitHeader<'a> {
197 unsafe {
199 SplitHeader {
200 cap: self.cap,
201 items: std::slice::from_raw_parts(self.items_ptr(), self.len),
202 table: std::slice::from_raw_parts(self.hashes_ptr(), hash_capacity(self.cap)),
203 }
204 }
205 }
206}
207
208trait HeaderMut<'a>: ThinMutExt<'a, Header> {
209 fn items_ptr_mut(&mut self) -> *mut KeyValuePair {
210 unsafe { self.ptr_mut().add(1).cast() }
212 }
213 fn hashes_ptr_mut(&mut self) -> *mut usize {
214 unsafe { self.items_ptr_mut().add(self.cap).cast() }
216 }
217 fn split_mut(mut self) -> SplitHeaderMut<'a> {
218 let len = self.len;
220 let hash_cap = hash_capacity(self.cap);
221 let item_ptr = self.items_ptr_mut();
222 let hash_ptr = self.hashes_ptr_mut();
223 unsafe {
224 SplitHeaderMut {
225 cap: self.cap,
226 items: std::slice::from_raw_parts_mut(item_ptr as *mut _, len),
227 table: std::slice::from_raw_parts_mut(hash_ptr as *mut _, hash_cap),
228 }
229 }
230 }
231
232 unsafe fn entry(self, key: IString) -> Entry<'a>;
234 unsafe fn entry_or_clone(self, key: &IString) -> Entry<'a>;
236
237 unsafe fn pop(&mut self) -> (IString, IValue) {
239 self.len -= 1;
240 let item = self.items_ptr_mut().add(self.len).read();
241 (item.key, item.value)
242 }
243 unsafe fn push(&mut self, key: IString, value: IValue) -> usize {
244 self.items_ptr_mut()
245 .add(self.len)
246 .write(KeyValuePair { key, value });
247 let res = self.len;
248 self.len += 1;
249 res
250 }
251 fn clear(&mut self) {
252 for item in self.reborrow().split_mut().table {
254 *item = usize::MAX;
255 }
256 while self.len > 0 {
258 unsafe {
260 self.pop();
261 }
262 }
263 }
264}
265
266impl<'a, T: ThinRefExt<'a, Header>> HeaderRef<'a> for T {}
267impl<'a> HeaderMut<'a> for ThinMut<'a, Header> {
268 unsafe fn entry(self, key: IString) -> Entry<'a> {
270 match self.split().find_bucket(&key) {
271 Err(bucket) => Entry::Vacant(VacantEntry {
272 header: self,
273 bucket,
274 key,
275 }),
276 Ok(bucket) => Entry::Occupied(OccupiedEntry {
277 header: self,
278 bucket,
279 }),
280 }
281 }
282 unsafe fn entry_or_clone(self, key: &IString) -> Entry<'a> {
284 match self.split().find_bucket(key) {
285 Err(bucket) => Entry::Vacant(VacantEntry {
286 header: self,
287 bucket,
288 key: key.clone(),
289 }),
290 Ok(bucket) => Entry::Occupied(OccupiedEntry {
291 header: self,
292 bucket,
293 }),
294 }
295 }
296}
297
298pub struct OccupiedEntry<'a> {
300 header: ThinMut<'a, Header>,
301 bucket: usize,
302}
303
304impl<'a> Debug for OccupiedEntry<'a> {
305 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
306 f.debug_struct("OccupiedEntry")
307 .field("key", self.key())
308 .field("value", &self.get())
309 .finish()
310 }
311}
312
313impl<'a> OccupiedEntry<'a> {
314 fn get_key_value(&self) -> (&IString, &IValue) {
315 let split = self.header.split();
317 unsafe {
318 let index = *split.table.get_unchecked(self.bucket);
319 let kvp = split.items.get_unchecked(index);
320 (&kvp.key, &kvp.value)
321 }
322 }
323 fn get_key_value_mut(&mut self) -> (&IString, &mut IValue) {
324 let split = self.header.reborrow().split_mut();
326 unsafe {
327 let index = *split.table.get_unchecked(self.bucket);
328 let kvp = split.items.get_unchecked_mut(index);
329 (&kvp.key, &mut kvp.value)
330 }
331 }
332 fn into_get_key_value_mut(self) -> (&'a IString, &'a mut IValue) {
333 let split = self.header.split_mut();
335 unsafe {
336 let index = *split.table.get_unchecked(self.bucket);
337 let kvp = split.items.get_unchecked_mut(index);
338 (&kvp.key, &mut kvp.value)
339 }
340 }
341 #[must_use]
343 pub fn key(&self) -> &IString {
344 self.get_key_value().0
345 }
346
347 pub fn remove_entry(mut self) -> (IString, IValue) {
349 unsafe {
351 self.header
352 .reborrow()
353 .split_mut()
354 .remove_bucket(self.bucket);
355 self.header.pop()
356 }
357 }
358 #[must_use]
360 pub fn get(&self) -> &IValue {
361 self.get_key_value().1
362 }
363 pub fn get_mut(&mut self) -> &mut IValue {
365 self.get_key_value_mut().1
366 }
367 #[must_use]
370 pub fn into_mut(self) -> &'a mut IValue {
371 self.into_get_key_value_mut().1
372 }
373
374 pub fn insert(&mut self, value: impl Into<IValue>) -> IValue {
376 mem::replace(self.get_mut(), value.into())
377 }
378
379 pub fn remove(self) -> IValue {
381 self.remove_entry().1
382 }
383}
384
385pub struct VacantEntry<'a> {
387 header: ThinMut<'a, Header>,
388 bucket: usize,
389 key: IString,
390}
391
392impl<'a> Debug for VacantEntry<'a> {
393 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
394 f.debug_struct("OccupiedEntry")
395 .field("key", self.key())
396 .finish()
397 }
398}
399
400impl<'a> VacantEntry<'a> {
401 #[must_use]
403 pub fn key(&self) -> &IString {
404 &self.key
405 }
406 #[must_use]
408 pub fn into_key(self) -> IString {
409 self.key
410 }
411 pub fn insert(mut self, value: impl Into<IValue>) -> &'a mut IValue {
414 unsafe {
417 let index = self.header.push(self.key, value.into());
418 let mut split = self.header.split_mut();
419 split.shift(self.bucket, index);
420 &mut split.items.last_mut().unwrap().value
421 }
422 }
423}
424
425#[derive(Debug)]
430pub enum Entry<'a> {
431 Occupied(OccupiedEntry<'a>),
433 Vacant(VacantEntry<'a>),
435}
436
437impl<'a> Entry<'a> {
438 pub fn or_insert(self, default: IValue) -> &'a mut IValue {
441 match self {
442 Entry::Occupied(occ) => occ.into_mut(),
443 Entry::Vacant(vac) => vac.insert(default),
444 }
445 }
446
447 pub fn or_insert_with(self, default: impl FnOnce() -> IValue) -> &'a mut IValue {
451 match self {
452 Entry::Occupied(occ) => occ.into_mut(),
453 Entry::Vacant(vac) => vac.insert(default()),
454 }
455 }
456
457 #[must_use]
459 pub fn key(&self) -> &IString {
460 match self {
461 Entry::Occupied(occ) => occ.key(),
462 Entry::Vacant(vac) => vac.key(),
463 }
464 }
465
466 pub fn and_modify(mut self, f: impl FnOnce(&mut IValue)) -> Self {
469 if let Entry::Occupied(occ) = &mut self {
470 f(occ.get_mut());
471 }
472 self
473 }
474}
475
476pub struct IntoIter {
479 reversed_object: IObject,
480}
481
482impl Debug for IntoIter {
483 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
484 f.debug_struct("IntoIter")
485 .field("reversed_object", &self.reversed_object)
486 .finish()
487 }
488}
489
490impl Iterator for IntoIter {
491 type Item = (IString, IValue);
492
493 fn next(&mut self) -> Option<Self::Item> {
494 if self.reversed_object.is_empty() {
495 None
496 } else {
497 Some(unsafe {
498 self.reversed_object.header_mut().pop()
500 })
501 }
502 }
503}
504
505impl ExactSizeIterator for IntoIter {
506 fn len(&self) -> usize {
507 self.reversed_object.len()
508 }
509}
510
511#[repr(transparent)]
520#[derive(Clone, size_of::SizeOf)]
521pub struct IObject(pub(crate) IValue);
522
523value_subtype_impls!(IObject, into_object, as_object, as_object_mut);
524
525static EMPTY_HEADER: Header = Header { len: 0, cap: 0 };
526
527impl IObject {
528 fn layout(cap: usize) -> Result<Layout, LayoutError> {
529 Ok(Layout::new::<Header>()
530 .extend(Layout::array::<KeyValuePair>(cap)?)?
531 .0
532 .extend(Layout::array::<usize>(hash_capacity(cap))?)?
533 .0
534 .pad_to_align())
535 }
536
537 fn alloc(cap: usize) -> *mut Header {
538 unsafe {
539 let hd = alloc(Self::layout(cap).unwrap()).cast::<Header>();
540 std::ptr::write(hd, Header { len: 0, cap });
541 let mut hd_mut = ThinMut::new(hd);
542 let hash_ptr = hd_mut.hashes_ptr_mut();
543 for i in 0..hash_capacity(cap) {
544 hash_ptr.add(i).write(usize::MAX);
545 }
546 hd
547 }
548 }
549
550 fn dealloc(ptr: *mut Header) {
551 unsafe {
552 let layout = Self::layout((*ptr).cap).unwrap();
553 dealloc(ptr.cast(), layout);
554 }
555 }
556
557 #[must_use]
559 pub fn new() -> Self {
560 unsafe { Self(IValue::new_ref(&EMPTY_HEADER, TypeTag::ObjectOrTrue)) }
561 }
562
563 #[must_use]
566 pub fn with_capacity(cap: usize) -> Self {
567 if cap == 0 {
568 Self::new()
569 } else {
570 Self(unsafe { IValue::new_ptr(Self::alloc(cap).cast(), TypeTag::ObjectOrTrue) })
571 }
572 }
573
574 fn header(&self) -> ThinRef<Header> {
575 unsafe { ThinRef::new(self.0.ptr().cast()) }
576 }
577
578 unsafe fn header_mut(&mut self) -> ThinMut<Header> {
580 ThinMut::new(self.0.ptr().cast())
581 }
582
583 fn is_static(&self) -> bool {
584 self.capacity() == 0
585 }
586 #[must_use]
589 pub fn capacity(&self) -> usize {
590 self.header().cap
591 }
592 #[must_use]
594 pub fn len(&self) -> usize {
595 self.header().len
596 }
597 #[must_use]
599 pub fn is_empty(&self) -> bool {
600 self.len() == 0
601 }
602
603 fn resize_internal(&mut self, cap: usize) {
604 let old_obj = mem::replace(self, Self::with_capacity(cap));
605 if !self.is_static() {
606 unsafe {
607 let mut hd = self.header_mut();
608 for (k, v) in old_obj {
609 if let Err(bucket) = hd.split().find_bucket(&k) {
610 let index = hd.push(k, v);
611 hd.reborrow().split_mut().shift(bucket, index);
612 }
613 }
614 }
615 }
616 }
617
618 pub fn reserve(&mut self, additional: usize) {
620 let hd = self.header();
621 let current_capacity = hd.cap;
622 let desired_capacity = hd.len.checked_add(additional).unwrap();
623 if current_capacity >= desired_capacity {
624 return;
625 }
626 self.resize_internal(cmp::max(current_capacity * 2, desired_capacity.max(4)));
627 }
628
629 pub fn entry(&mut self, key: impl Into<IString>) -> Entry {
631 self.reserve(1);
632 unsafe { self.header_mut().entry(key.into()) }
634 }
635 pub fn entry_or_clone(&mut self, key: &IString) -> Entry {
638 self.reserve(1);
639 unsafe { self.header_mut().entry_or_clone(key) }
641 }
642 pub fn keys(&self) -> impl Iterator<Item = &IString> {
644 self.iter().map(|x| x.0)
645 }
646 pub fn values(&self) -> impl Iterator<Item = &IValue> {
648 self.iter().map(|x| x.1)
649 }
650 #[must_use]
652 pub fn iter(&self) -> Iter {
653 Iter(self.header().split().items.iter())
654 }
655 pub fn values_mut(&mut self) -> impl Iterator<Item = &mut IValue> {
658 self.iter_mut().map(|x| x.1)
659 }
660 pub fn iter_mut(&mut self) -> IterMut {
662 IterMut(
663 if self.is_empty() {
664 &mut []
665 } else {
666 unsafe { self.header_mut().split_mut().items }
668 }
669 .iter_mut(),
670 )
671 }
672
673 pub fn clear(&mut self) {
675 if !self.is_empty() {
676 unsafe {
678 self.header_mut().clear();
679 }
680 }
681 }
682 pub fn get_key_value(&self, k: impl ObjectIndex) -> Option<(&IString, &IValue)> {
685 k.index_into(self)
686 }
687
688 pub fn get_key_value_mut(&mut self, k: impl ObjectIndex) -> Option<(&IString, &mut IValue)> {
691 k.index_into_mut(self)
692 }
693
694 pub fn get(&self, k: impl ObjectIndex) -> Option<&IValue> {
697 self.get_key_value(k).map(|x| x.1)
698 }
699
700 pub fn get_mut(&mut self, k: impl ObjectIndex) -> Option<&mut IValue> {
703 self.get_key_value_mut(k).map(|x| x.1)
704 }
705
706 pub fn contains_key(&self, k: impl ObjectIndex) -> bool {
708 self.get(k).is_some()
709 }
710
711 pub fn insert(&mut self, k: impl Into<IString>, v: impl Into<IValue>) -> Option<IValue> {
714 match self.entry(k) {
715 Entry::Occupied(mut occ) => Some(occ.insert(v)),
716 Entry::Vacant(vac) => {
717 vac.insert(v);
718 None
719 }
720 }
721 }
722
723 pub fn remove_entry(&mut self, k: impl ObjectIndex) -> Option<(IString, IValue)> {
726 k.remove(self)
727 }
728
729 pub fn remove(&mut self, k: impl ObjectIndex) -> Option<IValue> {
731 self.remove_entry(k).map(|x| x.1)
732 }
733
734 pub fn shrink_to_fit(&mut self) {
737 self.resize_internal(self.len());
738 }
739
740 pub fn retain(&mut self, mut f: impl FnMut(&IString, &mut IValue) -> bool) {
745 if !self.is_empty() {
746 let mut hd = unsafe { self.header_mut() };
748 let mut index = 0;
749 while index < hd.len {
750 let mut split = hd.reborrow().split_mut();
751
752 unsafe {
754 let kvp = split.items.get_unchecked_mut(index);
755 if f(&kvp.key, &mut kvp.value) {
756 index += 1;
757 } else {
758 let bucket = split.as_ref().find_bucket_from_index(index);
759 split.remove_bucket(bucket);
760 hd.pop();
761 }
762 }
763 }
764 }
765 }
766
767 pub(crate) fn clone_impl(&self) -> IValue {
768 let mut res = Self::with_capacity(self.len());
769 for (k, v) in self.iter() {
770 res.insert(k.clone(), v.clone());
771 }
772
773 res.0
774 }
775 pub(crate) fn drop_impl(&mut self) {
776 self.clear();
777 if !self.is_static() {
778 unsafe {
779 Self::dealloc(self.0.ptr().cast());
780 self.0.set_ref(&EMPTY_HEADER);
781 }
782 }
783 }
784}
785
786impl IntoIterator for IObject {
787 type Item = (IString, IValue);
788 type IntoIter = IntoIter;
789
790 fn into_iter(mut self) -> Self::IntoIter {
791 unsafe {
792 let split_header = self.header_mut().split_mut();
793 split_header.items.reverse();
794 }
795 IntoIter {
796 reversed_object: self,
797 }
798 }
799}
800
801impl PartialEq for IObject {
802 fn eq(&self, other: &Self) -> bool {
803 if self.0.raw_eq(&other.0) {
804 return true;
805 }
806 if self.len() != other.len() {
807 return false;
808 }
809 for (k, v) in self.iter() {
810 if other.get(k) != Some(v) {
811 return false;
812 }
813 }
814 true
815 }
816}
817
818impl Eq for IObject {}
819impl PartialOrd for IObject {
820 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
821 if self == other {
822 Some(Ordering::Equal)
823 } else {
824 None
825 }
826 }
827}
828
829impl Hash for IObject {
830 fn hash<H: Hasher>(&self, state: &mut H) {
831 self.len().hash(state);
832
833 let mut total_hash = 0_u64;
834 for item in self.iter() {
835 let mut h = DefaultHasher::new();
836 item.hash(&mut h);
837 total_hash = total_hash.wrapping_add(h.finish());
838 }
839 total_hash.hash(state);
840 }
841}
842
843impl<K: Into<IString>, V: Into<IValue>> Extend<(K, V)> for IObject {
844 fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
845 let iter = iter.into_iter();
846 self.reserve(iter.size_hint().0);
847 for (k, v) in iter {
848 self.insert(k, v);
849 }
850 }
851}
852
853impl<K: Into<IString>, V: Into<IValue>> FromIterator<(K, V)> for IObject {
854 fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
855 let mut res = IObject::new();
856 res.extend(iter);
857 res
858 }
859}
860
861impl<I: ObjectIndex> Index<I> for IObject {
862 type Output = IValue;
863
864 #[inline]
865 fn index(&self, index: I) -> &IValue {
866 index.index_into(self).unwrap().1
867 }
868}
869
870impl<I: ObjectIndex> IndexMut<I> for IObject {
871 #[inline]
872 fn index_mut(&mut self, index: I) -> &mut IValue {
873 index.index_or_insert(self)
874 }
875}
876
877mod private {
878 #[doc(hidden)]
879 pub trait Sealed {}
880 impl Sealed for usize {}
881 impl Sealed for &str {}
882 impl Sealed for &super::IString {}
883 impl<T: Sealed> Sealed for &T {}
884}
885
886pub trait ObjectIndex: private::Sealed + Copy {
889 #[doc(hidden)]
890 fn index_into(self, v: &IObject) -> Option<(&IString, &IValue)>;
891
892 #[doc(hidden)]
893 fn index_into_mut(self, v: &mut IObject) -> Option<(&IString, &mut IValue)>;
894
895 #[doc(hidden)]
896 fn index_or_insert(self, v: &mut IObject) -> &mut IValue;
897
898 #[doc(hidden)]
899 fn remove(self, v: &mut IObject) -> Option<(IString, IValue)>;
900}
901
902impl ObjectIndex for &str {
903 fn index_into(self, v: &IObject) -> Option<(&IString, &IValue)> {
904 IString::intern(self).index_into(v)
905 }
906
907 fn index_into_mut(self, v: &mut IObject) -> Option<(&IString, &mut IValue)> {
908 IString::intern(self).index_into_mut(v)
909 }
910
911 fn index_or_insert(self, v: &mut IObject) -> &mut IValue {
912 v.entry(IString::intern(self)).or_insert(IValue::NULL)
913 }
914
915 fn remove(self, v: &mut IObject) -> Option<(IString, IValue)> {
916 IString::intern(self).remove(v)
917 }
918}
919
920impl ObjectIndex for &IString {
921 fn index_into(self, v: &IObject) -> Option<(&IString, &IValue)> {
922 if v.is_empty() {
923 return None;
924 }
925 let hd = v.header().split();
926 if let Ok(bucket) = hd.find_bucket(self) {
927 unsafe {
929 let index = *hd.table.get_unchecked(bucket);
930 let item = hd.items.get_unchecked(index);
931 Some((&item.key, &item.value))
932 }
933 } else {
934 None
935 }
936 }
937
938 fn index_into_mut(self, v: &mut IObject) -> Option<(&IString, &mut IValue)> {
939 if v.is_empty() {
940 None
941 } else {
942 let hd = unsafe { v.header_mut().split_mut() };
944 if let Ok(bucket) = hd.as_ref().find_bucket(self) {
945 unsafe {
947 let index = *hd.table.get_unchecked(bucket);
948 let item = hd.items.get_unchecked_mut(index);
949 Some((&item.key, &mut item.value))
950 }
951 } else {
952 None
953 }
954 }
955 }
956
957 fn index_or_insert(self, v: &mut IObject) -> &mut IValue {
958 v.entry_or_clone(self).or_insert(IValue::NULL)
959 }
960
961 fn remove(self, v: &mut IObject) -> Option<(IString, IValue)> {
962 if v.is_empty() {
963 None
964 } else {
965 let mut hd = unsafe { v.header_mut() };
967 let mut split = hd.reborrow().split_mut();
968 if let Ok(bucket) = split.as_ref().find_bucket(self) {
969 unsafe {
971 split.remove_bucket(bucket);
972 Some(hd.pop())
973 }
974 } else {
975 None
976 }
977 }
978 }
979}
980
981impl<T: ObjectIndex> ObjectIndex for &T {
982 fn index_into(self, v: &IObject) -> Option<(&IString, &IValue)> {
983 (*self).index_into(v)
984 }
985
986 fn index_into_mut(self, v: &mut IObject) -> Option<(&IString, &mut IValue)> {
987 (*self).index_into_mut(v)
988 }
989
990 fn index_or_insert(self, v: &mut IObject) -> &mut IValue {
991 (*self).index_or_insert(v)
992 }
993
994 fn remove(self, v: &mut IObject) -> Option<(IString, IValue)> {
995 (*self).remove(v)
996 }
997}
998
999impl Debug for IObject {
1000 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1001 f.debug_map().entries(self.iter()).finish()
1002 }
1003}
1004
1005#[derive(Debug)]
1008pub struct Iter<'a>(std::slice::Iter<'a, KeyValuePair>);
1009
1010impl<'a> Iterator for Iter<'a> {
1011 type Item = (&'a IString, &'a IValue);
1012
1013 fn next(&mut self) -> Option<Self::Item> {
1014 self.0.next().map(|x| (&x.key, &x.value))
1015 }
1016}
1017
1018impl<'a> ExactSizeIterator for Iter<'a> {
1019 fn len(&self) -> usize {
1020 self.0.len()
1021 }
1022}
1023
1024#[derive(Debug)]
1027pub struct IterMut<'a>(std::slice::IterMut<'a, KeyValuePair>);
1028
1029impl<'a> Iterator for IterMut<'a> {
1030 type Item = (&'a IString, &'a mut IValue);
1031
1032 fn next(&mut self) -> Option<Self::Item> {
1033 self.0.next().map(|x| (&x.key, &mut x.value))
1034 }
1035}
1036
1037impl<'a> ExactSizeIterator for IterMut<'a> {
1038 fn len(&self) -> usize {
1039 self.0.len()
1040 }
1041}
1042
1043impl<'a> IntoIterator for &'a IObject {
1044 type Item = (&'a IString, &'a IValue);
1045 type IntoIter = Iter<'a>;
1046
1047 fn into_iter(self) -> Self::IntoIter {
1048 self.iter()
1049 }
1050}
1051
1052impl<'a> IntoIterator for &'a mut IObject {
1053 type Item = (&'a IString, &'a mut IValue);
1054 type IntoIter = IterMut<'a>;
1055
1056 fn into_iter(self) -> Self::IntoIter {
1057 self.iter_mut()
1058 }
1059}
1060
1061impl<K: Into<IString>, V: Into<IValue>> From<HashMap<K, V>> for IObject {
1062 fn from(other: HashMap<K, V>) -> Self {
1063 let mut res = Self::with_capacity(other.len());
1064 res.extend(other.into_iter().map(|(k, v)| (k.into(), v.into())));
1065 res
1066 }
1067}
1068
1069impl<K: Into<IString>, V: Into<IValue>> From<BTreeMap<K, V>> for IObject {
1070 fn from(other: BTreeMap<K, V>) -> Self {
1071 let mut res = Self::with_capacity(other.len());
1072 res.extend(other.into_iter().map(|(k, v)| (k.into(), v.into())));
1073 res
1074 }
1075}
1076
1077#[cfg(feature = "indexmap")]
1078impl<K: Into<IString>, V: Into<IValue>> From<IndexMap<K, V>> for IObject {
1079 fn from(other: IndexMap<K, V>) -> Self {
1080 let mut res = Self::with_capacity(other.len());
1081 res.extend(other.into_iter().map(|(k, v)| (k.into(), v.into())));
1082 res
1083 }
1084}
1085
1086impl Default for IObject {
1087 fn default() -> Self {
1088 Self::new()
1089 }
1090}
1091
1092#[cfg(test)]
1093mod tests {
1094 use super::*;
1095
1096 #[mockalloc::test]
1097 fn can_create() {
1098 let x = IObject::new();
1099 let y = IObject::with_capacity(10);
1100
1101 assert_eq!(x, y);
1102 }
1103
1104 #[mockalloc::test]
1105 fn can_collect() {
1106 let x = vec![
1107 ("a", IValue::NULL),
1108 ("b", IValue::TRUE),
1109 ("c", IValue::FALSE),
1110 ];
1111 let y: IObject = x.into_iter().collect();
1112
1113 assert_eq!(y, y.clone());
1114 assert_eq!(y.len(), 3);
1115 assert_eq!(y["a"], IValue::NULL);
1116 assert_eq!(y["b"], IValue::TRUE);
1117 assert_eq!(y["c"], IValue::FALSE);
1118 }
1119
1120 #[mockalloc::test]
1121 fn can_insert() {
1122 let mut x = IObject::new();
1123 x.insert("a", IValue::NULL);
1124 x.insert("b", IValue::TRUE);
1125 x.insert("c", IValue::FALSE);
1126
1127 assert_eq!(x.len(), 3);
1128 assert_eq!(x["a"], IValue::NULL);
1129 assert_eq!(x["b"], IValue::TRUE);
1130 assert_eq!(x["c"], IValue::FALSE);
1131 }
1132
1133 #[mockalloc::test]
1134 fn can_nest() {
1135 let mut x = IObject::new();
1136 x.insert("a", IValue::NULL);
1137 x.insert("b", x.clone());
1138 x.insert("c", IValue::FALSE);
1139 x.insert("d", x.clone());
1140
1141 assert_eq!(x.len(), 4);
1142 assert_eq!(x["a"], IValue::NULL);
1143 assert_eq!(x["b"].len(), Some(1));
1144 assert_eq!(x["c"], IValue::FALSE);
1145 assert_eq!(x["d"].len(), Some(3));
1146 }
1147
1148 #[mockalloc::test]
1149 fn can_remove_and_shrink() {
1150 let x = vec![
1151 ("a", IValue::NULL),
1152 ("b", IValue::TRUE),
1153 ("c", IValue::FALSE),
1154 ];
1155 let mut y: IObject = x.into_iter().collect();
1156 assert_eq!(y.len(), 3);
1157 assert_eq!(y.capacity(), 4);
1158
1159 assert_eq!(y.remove("b"), Some(IValue::TRUE));
1160 assert_eq!(y.remove("b"), None);
1161 assert_eq!(y.remove("d"), None);
1162
1163 assert_eq!(y.len(), 2);
1164 assert_eq!(y.capacity(), 4);
1165 assert_eq!(y["a"], IValue::NULL);
1166 assert_eq!(y["c"], IValue::FALSE);
1167
1168 y.shrink_to_fit();
1169 assert_eq!(y.len(), 2);
1170 assert_eq!(y.capacity(), 2);
1171 assert_eq!(y["a"], IValue::NULL);
1172 assert_eq!(y["c"], IValue::FALSE);
1173 }
1174
1175 #[cfg(not(miri))]
1177 #[mockalloc::test]
1178 fn stress_test() {
1179 use rand::prelude::*;
1180
1181 for i in 0..10 {
1182 let mut rng = StdRng::seed_from_u64(i);
1184 let range = 0..10000;
1185 let mut ops: Vec<i32> = range.clone().chain(range).collect();
1186 ops.shuffle(&mut rng);
1187
1188 let mut x = IObject::new();
1189 for op in ops {
1190 let k = IString::intern(&op.to_string());
1191 if x.contains_key(&k) {
1192 x.remove(&k);
1193 } else {
1194 x.insert(k, op);
1195 }
1196 }
1197 assert_eq!(x, IObject::new());
1198 }
1199 }
1200}