1use std::cell::Cell;
2use std::hash::{Hash, Hasher};
3use std::rc::Rc;
4
5thread_local! {
6 static CHAMP_PLACEMENT_HASHING: Cell<bool> = const { Cell::new(false) };
7}
8
9pub(crate) fn with_champ_placement_hash<T>(f: impl FnOnce() -> T) -> T {
10 CHAMP_PLACEMENT_HASHING.with(|active| {
11 let previous = active.replace(true);
12 let result = f();
13 active.set(previous);
14 result
15 })
16}
17
18pub(crate) fn champ_placement_hashing() -> bool {
19 CHAMP_PLACEMENT_HASHING.with(Cell::get)
20}
21
22use crate::lang::hash::JavaHash;
23use crate::lang::protocol::{
24 HashType, IAssoc, IColl, IConj, ICount, IDisplay, IDissoc, IEmpty, IEquality, IFind, IHash,
25 ILookup, IMetadata, IMutable, IObjType, IPersistent, IToMutable, IToPersistent, MetaType,
26 ObjType,
27};
28
29const SHIFT: usize = 5;
30const MASK: u64 = 0x1f;
31
32#[derive(Debug, Clone)]
45enum Slot<K, V> {
46 Entry { hash: u64, key: K, value: V },
47 Node(Rc<Node<K, V>>),
48}
49
50#[derive(Debug, Clone)]
51struct DataNode<K, V> {
52 edit: Cell<u64>,
53 datamap: u32,
54 nodemap: u32,
55 slots: Vec<Slot<K, V>>,
56}
57
58#[derive(Debug, Clone)]
59struct CollisionNode<K, V> {
60 edit: Cell<u64>,
61 hash: u64,
62 entries: Vec<(K, V)>,
63}
64
65#[derive(Debug, Clone)]
66enum Node<K, V> {
67 Data(DataNode<K, V>),
68 Collision(CollisionNode<K, V>),
69}
70
71impl<K, V> Node<K, V> {
72 fn empty() -> Rc<Self> {
73 Rc::new(Self::Data(DataNode {
74 edit: Cell::new(0),
75 datamap: 0,
76 nodemap: 0,
77 slots: Vec::new(),
78 }))
79 }
80 fn set_edit(&self, token: u64) {
81 match self {
82 Node::Data(d) => d.edit.set(token),
83 Node::Collision(c) => c.edit.set(token),
84 }
85 }
86 fn is_single(&self) -> bool {
87 match self {
88 Node::Data(d) => d.nodemap == 0 && d.datamap.count_ones() == 1,
89 Node::Collision(c) => c.entries.len() == 1,
90 }
91 }
92}
93
94fn key_hash<K: Hash>(key: &K) -> u64 {
103 #[derive(Default)]
104 struct Probe {
105 captured: Option<u64>,
106 fallback: std::collections::hash_map::DefaultHasher,
107 }
108 impl Hasher for Probe {
109 fn finish(&self) -> u64 {
110 self.captured.unwrap_or_else(|| self.fallback.finish())
111 }
112 fn write(&mut self, bytes: &[u8]) {
113 self.fallback.write(bytes);
114 }
115 fn write_u64(&mut self, value: u64) {
116 if self.captured.is_none() {
117 self.captured = Some(value);
118 }
119 }
120 }
121 let mut probe = Probe::default();
122 with_champ_placement_hash(|| key.hash(&mut probe));
123 let hash = probe.finish();
124 if probe.captured.is_some() {
125 (hash as u32) as u64
126 } else {
127 hash
128 }
129}
130fn mask(hash: u64, shift: usize) -> usize {
131 ((hash >> shift) & MASK) as usize
132}
133fn bit(hash: u64, shift: usize) -> u32 {
134 1u32 << mask(hash, shift)
135}
136fn index(bitmap: u32, bit: u32) -> usize {
137 (bitmap & (bit - 1)).count_ones() as usize
138}
139fn node_slot<K, V>(d: &DataNode<K, V>, bit: u32) -> usize {
143 d.datamap.count_ones() as usize + (d.nodemap.count_ones() as usize - 1 - index(d.nodemap, bit))
144}
145
146fn ensure<'a, K: Clone, V: Clone>(
152 node: &'a mut Rc<Node<K, V>>,
153 edit: Option<u64>,
154) -> &'a mut Node<K, V> {
155 match edit {
156 Some(token) => {
157 let n = Rc::make_mut(node);
158 n.set_edit(token);
159 n
160 }
161 None => {
162 let fresh = (**node).clone();
163 fresh.set_edit(0);
164 *node = Rc::new(fresh);
165 Rc::get_mut(node).expect("freshly cloned node is uniquely owned")
166 }
167 }
168}
169
170fn merge_two<K: Clone, V: Clone>(
176 edit: Option<u64>,
177 shift: usize,
178 a_hash: u64,
179 a_key: K,
180 a_val: V,
181 b_hash: u64,
182 b_key: K,
183 b_val: V,
184) -> Rc<Node<K, V>> {
185 let e = edit.unwrap_or(0);
186 if shift > 32 && a_hash == b_hash {
187 return Rc::new(Node::Collision(CollisionNode {
188 edit: Cell::new(e),
189 hash: a_hash,
190 entries: vec![(a_key, a_val), (b_key, b_val)],
191 }));
192 }
193 let abit = bit(a_hash, shift);
194 let bbit = bit(b_hash, shift);
195 if abit == bbit {
196 return Rc::new(Node::Data(DataNode {
197 edit: Cell::new(e),
198 datamap: 0,
199 nodemap: abit,
200 slots: vec![Slot::Node(merge_two(
201 edit,
202 shift + SHIFT,
203 a_hash,
204 a_key,
205 a_val,
206 b_hash,
207 b_key,
208 b_val,
209 ))],
210 }));
211 }
212 let (first, second) = if mask(a_hash, shift) < mask(b_hash, shift) {
213 (
214 Slot::Entry {
215 hash: a_hash,
216 key: a_key,
217 value: a_val,
218 },
219 Slot::Entry {
220 hash: b_hash,
221 key: b_key,
222 value: b_val,
223 },
224 )
225 } else {
226 (
227 Slot::Entry {
228 hash: b_hash,
229 key: b_key,
230 value: b_val,
231 },
232 Slot::Entry {
233 hash: a_hash,
234 key: a_key,
235 value: a_val,
236 },
237 )
238 };
239 Rc::new(Node::Data(DataNode {
240 edit: Cell::new(e),
241 datamap: abit | bbit,
242 nodemap: 0,
243 slots: vec![first, second],
244 }))
245}
246
247fn merge_node<K: Clone, V: Clone>(
251 edit: Option<u64>,
252 shift: usize,
253 node_hash: u64,
254 node: Rc<Node<K, V>>,
255 hash: u64,
256 key: K,
257 value: V,
258) -> Rc<Node<K, V>> {
259 let e = edit.unwrap_or(0);
260 let abit = bit(node_hash, shift);
261 let bbit = bit(hash, shift);
262 if abit == bbit {
263 return Rc::new(Node::Data(DataNode {
264 edit: Cell::new(e),
265 datamap: 0,
266 nodemap: abit,
267 slots: vec![Slot::Node(merge_node(
268 edit,
269 shift + SHIFT,
270 node_hash,
271 node,
272 hash,
273 key,
274 value,
275 ))],
276 }));
277 }
278 Rc::new(Node::Data(DataNode {
279 edit: Cell::new(e),
280 datamap: bbit,
281 nodemap: abit,
282 slots: vec![Slot::Entry { hash, key, value }, Slot::Node(node)],
283 }))
284}
285
286fn assoc_node<K: Clone + Eq, V: Clone>(
291 node: &mut Rc<Node<K, V>>,
292 edit: Option<u64>,
293 shift: usize,
294 hash: u64,
295 key: K,
296 value: V,
297) -> bool {
298 enum Act<K, V> {
299 CollisionReplace(usize),
300 CollisionPush,
301 CollisionMerge,
302 DataReplace(usize),
303 DataMerge { i: usize, b: u32, old: (u64, K, V) },
304 DataRecurse(usize),
305 DataInsert { i: usize, b: u32 },
306 }
307 let act = match node.as_ref() {
308 Node::Collision(c) => {
309 if c.hash == hash {
310 match c.entries.iter().position(|(k, _)| k == &key) {
311 Some(i) => Act::CollisionReplace(i),
312 None => Act::CollisionPush,
313 }
314 } else {
315 Act::CollisionMerge
316 }
317 }
318 Node::Data(d) => {
319 let b = bit(hash, shift);
320 if d.datamap & b != 0 {
321 let i = index(d.datamap, b);
322 match &d.slots[i] {
323 Slot::Entry {
324 hash: old_hash,
325 key: old_key,
326 value: old_value,
327 } => {
328 if old_key == &key {
329 Act::DataReplace(i)
330 } else {
331 Act::DataMerge {
332 i,
333 b,
334 old: (*old_hash, old_key.clone(), old_value.clone()),
335 }
336 }
337 }
338 Slot::Node(_) => unreachable!("data region holds entries only"),
339 }
340 } else if d.nodemap & b != 0 {
341 Act::DataRecurse(node_slot(d, b))
342 } else {
343 Act::DataInsert {
344 i: index(d.datamap, b),
345 b,
346 }
347 }
348 }
349 };
350 match act {
351 Act::CollisionReplace(i) => {
352 if let Node::Collision(c) = ensure(node, edit) {
353 c.entries[i].1 = value;
354 }
355 false
356 }
357 Act::CollisionPush => {
358 if let Node::Collision(c) = ensure(node, edit) {
359 c.entries.push((key, value));
360 }
361 true
362 }
363 Act::CollisionMerge => {
364 let node_hash = match node.as_ref() {
365 Node::Collision(c) => c.hash,
366 _ => unreachable!(),
367 };
368 let old = std::mem::replace(node, Node::empty());
369 *node = merge_node(edit, shift, node_hash, old, hash, key, value);
370 true
371 }
372 Act::DataReplace(i) => {
373 if let Node::Data(d) = ensure(node, edit) {
374 d.slots[i] = Slot::Entry { hash, key, value };
375 }
376 false
377 }
378 Act::DataMerge { i, b, old } => {
379 let (old_hash, old_key, old_value) = old;
380 let merged = merge_two(
381 edit,
382 shift + SHIFT,
383 old_hash,
384 old_key,
385 old_value,
386 hash,
387 key,
388 value,
389 );
390 if let Node::Data(d) = ensure(node, edit) {
391 d.slots.remove(i);
394 d.datamap ^= b;
395 d.nodemap |= b;
396 let p = index(d.nodemap, b);
397 let pos =
398 d.datamap.count_ones() as usize + (d.nodemap.count_ones() as usize - 1 - p);
399 d.slots.insert(pos, Slot::Node(merged));
400 }
401 true
402 }
403 Act::DataRecurse(i) => {
404 let n = ensure(node, edit);
405 match n {
406 Node::Data(d) => match &mut d.slots[i] {
407 Slot::Node(child) => assoc_node(child, edit, shift + SHIFT, hash, key, value),
408 Slot::Entry { .. } => unreachable!("node region holds nodes only"),
409 },
410 _ => unreachable!(),
411 }
412 }
413 Act::DataInsert { i, b } => {
414 if let Node::Data(d) = ensure(node, edit) {
415 d.slots.insert(i, Slot::Entry { hash, key, value });
416 d.datamap |= b;
417 }
418 true
419 }
420 }
421}
422
423fn find_node<'a, K: Eq, V>(
424 node: &'a Node<K, V>,
425 shift: usize,
426 hash: u64,
427 key: &K,
428) -> Option<(&'a K, &'a V)> {
429 match node {
430 Node::Collision(c) if c.hash == hash => c
431 .entries
432 .iter()
433 .find(|(k, _)| k == key)
434 .map(|(k, v)| (k, v)),
435 Node::Collision(_) => None,
436 Node::Data(d) => {
437 let b = bit(hash, shift);
438 if d.datamap & b != 0 {
439 match &d.slots[index(d.datamap, b)] {
440 Slot::Entry {
441 key: k, value: v, ..
442 } if k == key => Some((k, v)),
443 _ => None,
444 }
445 } else if d.nodemap & b != 0 {
446 match &d.slots[node_slot(d, b)] {
447 Slot::Node(child) => find_node(child, shift + SHIFT, hash, key),
448 Slot::Entry { .. } => None,
449 }
450 } else {
451 None
452 }
453 }
454 }
455}
456
457fn without_present<K: Clone + Eq, V: Clone>(
465 node: &mut Rc<Node<K, V>>,
466 edit: Option<u64>,
467 shift: usize,
468 hash: u64,
469 key: &K,
470) {
471 enum Act {
472 DataRemove { i: usize, b: u32 },
473 DataCollapse { keep: usize, new_datamap: u32 },
474 Recurse { i: usize, b: u32 },
475 CollisionRemove(usize),
476 CollisionToData,
477 CollisionToEmpty,
478 }
479 let act = match node.as_ref() {
480 Node::Collision(c) => {
481 debug_assert_eq!(c.hash, hash);
482 match c.entries.len() {
483 1 => Act::CollisionToEmpty,
484 2 => Act::CollisionToData,
485 _ => Act::CollisionRemove(
486 c.entries
487 .iter()
488 .position(|(k, _)| k == key)
489 .expect("key is present"),
490 ),
491 }
492 }
493 Node::Data(d) => {
494 let b = bit(hash, shift);
495 if d.datamap & b != 0 {
496 let i = index(d.datamap, b);
497 if d.datamap.count_ones() == 2 && d.nodemap == 0 {
498 let keep = if i == 0 { 1 } else { 0 };
499 let new_datamap = if shift == 0 {
504 d.datamap ^ b
505 } else {
506 bit(hash, 0)
507 };
508 Act::DataCollapse { keep, new_datamap }
509 } else {
510 Act::DataRemove { i, b }
511 }
512 } else {
513 debug_assert!(d.nodemap & b != 0, "key is present below");
514 Act::Recurse {
515 i: node_slot(d, b),
516 b,
517 }
518 }
519 }
520 };
521 match act {
522 Act::DataRemove { i, b } => {
523 if let Node::Data(d) = ensure(node, edit) {
524 d.slots.remove(i);
525 d.datamap ^= b;
526 }
527 }
528 Act::DataCollapse { keep, new_datamap } => {
529 let kept = match node.as_ref() {
530 Node::Data(d) => d.slots[keep].clone(),
531 _ => unreachable!(),
532 };
533 *node = Rc::new(Node::Data(DataNode {
534 edit: Cell::new(edit.unwrap_or(0)),
535 datamap: new_datamap,
536 nodemap: 0,
537 slots: vec![kept],
538 }));
539 }
540 Act::Recurse { i, b } => {
541 let n = ensure(node, edit);
542 let d = match n {
543 Node::Data(d) => d,
544 _ => unreachable!(),
545 };
546 let child_single = match &mut d.slots[i] {
547 Slot::Node(child) => {
548 without_present(child, edit, shift + SHIFT, hash, key);
549 child.is_single()
550 }
551 Slot::Entry { .. } => unreachable!("node region holds nodes only"),
552 };
553 if !child_single {
554 return;
555 }
556 if d.datamap == 0 && d.nodemap.count_ones() == 1 {
557 let child = match &d.slots[i] {
559 Slot::Node(c) => c.clone(),
560 _ => unreachable!(),
561 };
562 *node = child;
563 return;
564 }
565 let child = match &d.slots[i] {
568 Slot::Node(c) => c.clone(),
569 _ => unreachable!(),
570 };
571 let (ehash, ekey, evalue) = match child.as_ref() {
572 Node::Data(cd) => match &cd.slots[0] {
573 Slot::Entry { hash, key, value } => (*hash, key.clone(), value.clone()),
574 Slot::Node(_) => unreachable!("single-pair node holds an entry"),
575 },
576 Node::Collision(cc) => {
577 let (k, v) = cc.entries[0].clone();
578 (cc.hash, k, v)
579 }
580 };
581 let p = index(d.nodemap, b);
582 let node_pos =
583 d.datamap.count_ones() as usize + (d.nodemap.count_ones() as usize - 1 - p);
584 d.slots.remove(node_pos);
585 d.nodemap ^= b;
586 d.datamap |= b;
587 let data_pos = index(d.datamap, b);
588 d.slots.insert(
589 data_pos,
590 Slot::Entry {
591 hash: ehash,
592 key: ekey,
593 value: evalue,
594 },
595 );
596 }
597 Act::CollisionRemove(i) => {
598 if let Node::Collision(c) = ensure(node, edit) {
599 c.entries.remove(i);
600 }
601 }
602 Act::CollisionToData => {
603 let (k, v) = match node.as_ref() {
606 Node::Collision(c) => c
607 .entries
608 .iter()
609 .find(|(k, _)| k != key)
610 .cloned()
611 .expect("other entry is present"),
612 _ => unreachable!(),
613 };
614 *node = Rc::new(Node::Data(DataNode {
615 edit: Cell::new(edit.unwrap_or(0)),
616 datamap: bit(hash, 0),
617 nodemap: 0,
618 slots: vec![Slot::Entry {
619 hash,
620 key: k,
621 value: v,
622 }],
623 }));
624 }
625 Act::CollisionToEmpty => {
626 *node = Rc::new(Node::Data(DataNode {
627 edit: Cell::new(edit.unwrap_or(0)),
628 datamap: 0,
629 nodemap: 0,
630 slots: Vec::new(),
631 }));
632 }
633 }
634}
635
636fn collect<'a, K, V>(node: &'a Node<K, V>, out: &mut Vec<(&'a K, &'a V)>) {
637 match node {
638 Node::Collision(c) => out.extend(c.entries.iter().map(|(k, v)| (k, v))),
639 Node::Data(d) => {
640 let data_arity = d.datamap.count_ones() as usize;
641 for slot in &d.slots[..data_arity] {
642 match slot {
643 Slot::Entry { key, value, .. } => out.push((key, value)),
644 Slot::Node(_) => unreachable!("data region holds entries only"),
645 }
646 }
647 for slot in &d.slots[data_arity..] {
650 match slot {
651 Slot::Node(child) => collect(child, out),
652 Slot::Entry { .. } => unreachable!("node region holds nodes only"),
653 }
654 }
655 }
656 }
657}
658
659#[derive(Debug, Clone)]
660pub struct Standard<K, V> {
661 metadata: Option<Rc<crate::lang::data::Metadata>>,
662 root: Rc<Node<K, V>>,
663 size: usize,
664}
665impl<K, V> Default for Standard<K, V> {
666 fn default() -> Self {
667 Self {
668 metadata: None,
669 root: Node::empty(),
670 size: 0,
671 }
672 }
673}
674impl<K: Clone + Eq + Hash, V: Clone> Standard<K, V> {
675 pub fn new() -> Self {
676 Self::default()
677 }
678 pub fn len(&self) -> usize {
679 self.size
680 }
681 pub fn is_empty(&self) -> bool {
682 self.size == 0
683 }
684 pub fn get(&self, key: &K) -> Option<&V> {
685 find_node(&self.root, 0, key_hash(key), key).map(|(_, v)| v)
686 }
687 pub fn find_entry(&self, key: &K) -> Option<(&K, &V)> {
688 find_node(&self.root, 0, key_hash(key), key)
689 }
690 pub fn assoc_value(&self, key: K, value: V) -> Self {
691 let mut root = self.root.clone();
692 let added = assoc_node(&mut root, None, 0, key_hash(&key), key, value);
693 Self {
694 metadata: self.metadata.clone(),
695 root,
696 size: self.size + usize::from(added),
697 }
698 }
699 pub fn assoc_value_owned(mut self, key: K, value: V) -> Self {
703 let added = assoc_node(&mut self.root, Some(0), 0, key_hash(&key), key, value);
704 self.size += usize::from(added);
705 self
706 }
707 pub fn dissoc_value(&self, key: &K) -> Self {
708 let hash = key_hash(key);
709 if find_node(&self.root, 0, hash, key).is_none() {
710 return self.clone();
711 }
712 let mut root = self.root.clone();
713 without_present(&mut root, None, 0, hash, key);
714 Self {
715 metadata: self.metadata.clone(),
716 root,
717 size: self.size - 1,
718 }
719 }
720 pub fn iter(&self) -> std::vec::IntoIter<(&K, &V)> {
721 self.entries().into_iter()
722 }
723 pub fn entries(&self) -> Vec<(&K, &V)> {
724 let mut out = Vec::with_capacity(self.size);
725 collect(&self.root, &mut out);
726 out
727 }
728 pub fn shares_root_with(&self, other: &Self) -> bool {
729 Rc::ptr_eq(&self.root, &other.root)
730 }
731}
732impl<K: Clone + Eq + Hash, V: Clone> FromIterator<(K, V)> for Standard<K, V> {
733 fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
734 iter.into_iter()
735 .fold(Self::new(), |map, (k, v)| map.assoc_value(k, v))
736 }
737}
738impl<K: Clone + Eq + Hash, V: Clone> IntoIterator for Standard<K, V> {
739 type Item = (K, V);
740 type IntoIter = std::vec::IntoIter<(K, V)>;
741 fn into_iter(self) -> Self::IntoIter {
742 self.entries()
743 .into_iter()
744 .map(|(k, v)| (k.clone(), v.clone()))
745 .collect::<Vec<_>>()
746 .into_iter()
747 }
748}
749impl<K: Clone + Eq + Hash, V: Clone + PartialEq> PartialEq for Standard<K, V> {
750 fn eq(&self, other: &Self) -> bool {
751 self.size == other.size && self.entries().iter().all(|(k, v)| other.get(k) == Some(*v))
752 }
753}
754impl<K: Clone + Eq + Hash, V: Clone> ICount for Standard<K, V> {
755 fn count(&self) -> usize {
756 self.size
757 }
758}
759impl<K: Clone + Eq + Hash, V: Clone> IAssoc<K, V> for Standard<K, V> {
760 type Output = Self;
761 fn assoc(&self, key: K, value: V) -> Self {
762 self.assoc_value(key, value)
763 }
764}
765impl<K: Clone + Eq + Hash, V: Clone> IDissoc<K> for Standard<K, V> {
766 type Output = Self;
767 fn dissoc(&self, key: &K) -> Self {
768 self.dissoc_value(key)
769 }
770}
771impl<K: Clone + Eq + Hash, V: Clone> IFind<K> for Standard<K, V> {
772 type Output = (K, V);
773 fn find(&self, key: &K) -> Option<Self::Output> {
774 self.find_entry(key).map(|(k, v)| (k.clone(), v.clone()))
775 }
776}
777impl<K: Clone + Eq + Hash, V: Clone> ILookup<K, V> for Standard<K, V> {
778 type Keys = std::vec::IntoIter<K>;
779 type Values = std::vec::IntoIter<V>;
780 fn keys(&self) -> Self::Keys {
781 self.entries()
782 .into_iter()
783 .map(|(k, _)| k.clone())
784 .collect::<Vec<_>>()
785 .into_iter()
786 }
787 fn vals(&self) -> Self::Values {
788 self.entries()
789 .into_iter()
790 .map(|(_, v)| v.clone())
791 .collect::<Vec<_>>()
792 .into_iter()
793 }
794}
795impl<K: Clone + Eq + Hash, V: Clone> IEmpty for Standard<K, V> {
796 type Output = Self;
797 fn empty(&self) -> Self {
798 Self::new().with_meta(self.metadata.clone())
799 }
800}
801impl<K: Clone + Eq + Hash, V: Clone> IMetadata for Standard<K, V> {
802 type Metadata = Rc<crate::lang::data::Metadata>;
803 fn meta(&self) -> Option<&Self::Metadata> {
804 self.metadata.as_ref()
805 }
806 fn with_meta(&self, metadata: Option<Self::Metadata>) -> Self {
807 Self {
808 metadata,
809 ..self.clone()
810 }
811 }
812
813 fn metatype(&self) -> MetaType {
814 MetaType::Map
815 }
816}
817impl<K: Clone + Eq + Hash, V: Clone> IPersistent for Standard<K, V> {}
818impl<K: Clone + Eq + Hash, V: Clone> IConj<(K, V)> for Standard<K, V> {
819 type Output = Self;
820 fn conj(&self, (key, value): (K, V)) -> Self {
821 self.assoc_value(key, value)
822 }
823}
824impl<K: Clone + Eq + Hash, V: Clone + PartialEq> IEquality for Standard<K, V> {
825 fn equality(&self, other: &Self) -> bool {
826 self == other
827 }
828}
829impl<K: Clone + Eq + Hash + std::fmt::Debug, V: Clone + std::fmt::Debug> IDisplay
830 for Standard<K, V>
831{
832 fn display(&self) -> String {
833 format!(
834 "{{{}}}",
835 self.entries()
836 .iter()
837 .map(|(k, v)| format!("{k:?} {v:?}"))
838 .collect::<Vec<_>>()
839 .join(" ")
840 )
841 }
842}
843impl<K: Clone + Eq + Hash + JavaHash, V: Clone + Hash + JavaHash> IHash for Standard<K, V> {
844 fn hash_calc(&self, hash_type: HashType) -> u64 {
845 crate::lang::hash::compose_unordered(
850 "MAP",
851 self.entries().iter().map(|(k, v)| {
852 crate::lang::hash::compose_entry(k.java_hash(hash_type), v.java_hash(hash_type))
853 }),
854 ) as u64
855 }
856}
857impl<K: Clone + Eq + Hash + std::fmt::Debug, V: Clone + std::fmt::Debug> IObjType
858 for Standard<K, V>
859{
860 fn obj_type(&self) -> ObjType {
861 ObjType::Map
862 }
863}
864impl<K, V> IColl<(K, V)> for Standard<K, V>
865where
866 K: Clone + Eq + Hash + JavaHash + std::fmt::Debug,
867 V: Clone + PartialEq + Hash + JavaHash + std::fmt::Debug,
868{
869 fn start_string(&self) -> &'static str {
870 "{"
871 }
872 fn end_string(&self) -> &'static str {
873 "}"
874 }
875}
876impl<K: Clone + Eq + Hash, V: Clone> IToMutable for Standard<K, V> {
877 type Mutable = Mutable<K, V>;
878 fn to_mutable(&self) -> Self::Mutable {
879 Mutable {
880 editable: Cell::new(true),
881 token: fresh_edit(),
882 standard: self.clone(),
883 }
884 }
885}
886
887thread_local! {
888 static NEXT_EDIT: Cell<u64> = const { Cell::new(1) };
889}
890fn fresh_edit() -> u64 {
891 NEXT_EDIT.with(|c| {
892 let token = c.get();
893 c.set(token + 1);
894 token
895 })
896}
897
898#[derive(Debug, Clone)]
899pub struct Mutable<K, V> {
900 editable: Cell<bool>,
901 token: u64,
902 standard: Standard<K, V>,
903}
904impl<K: Clone + Eq + Hash, V: Clone> Mutable<K, V> {
905 fn check(&self) {
906 assert!(self.editable.get(), "mutable map used after to_persistent")
907 }
908 pub fn assoc(&mut self, key: K, value: V) -> &mut Self {
909 self.check();
910 let hash = key_hash(&key);
911 let mut root = std::mem::replace(&mut self.standard.root, Node::empty());
914 let added = assoc_node(&mut root, Some(self.token), 0, hash, key, value);
915 self.standard.root = root;
916 self.standard.size += usize::from(added);
917 self
918 }
919 pub fn dissoc(&mut self, key: &K) -> &mut Self {
920 self.check();
921 let hash = key_hash(key);
922 if find_node(&self.standard.root, 0, hash, key).is_some() {
923 let mut root = std::mem::replace(&mut self.standard.root, Node::empty());
924 without_present(&mut root, Some(self.token), 0, hash, key);
925 self.standard.root = root;
926 self.standard.size -= 1;
927 }
928 self
929 }
930}
931impl<K: Clone + Eq + Hash, V: Clone> std::ops::Deref for Mutable<K, V> {
932 type Target = Standard<K, V>;
933 fn deref(&self) -> &Self::Target {
934 self.check();
935 &self.standard
936 }
937}
938impl<K, V> IMutable for Mutable<K, V> {}
939impl<K: Clone + Eq + Hash, V: Clone> IToPersistent for Mutable<K, V> {
940 type Persistent = Standard<K, V>;
941 fn to_persistent(&mut self) -> Self::Persistent {
942 self.check();
943 self.editable.set(false);
944 self.standard.clone()
945 }
946}
947
948#[cfg(test)]
949mod tests {
950 use super::Standard;
951 use crate::core::Value;
952 use crate::lang::protocol::{IEmpty, IMetadata, IToMutable, IToPersistent};
953 use std::collections::HashMap;
954 use std::hash::{Hash, Hasher};
955
956 #[derive(Clone, Debug, Eq, PartialEq)]
957 struct Collision(i32);
958 impl Hash for Collision {
959 fn hash<H: Hasher>(&self, state: &mut H) {
960 0.hash(state)
961 }
962 }
963
964 #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
968 struct Key(u64);
969 impl Hash for Key {
970 fn hash<H: Hasher>(&self, state: &mut H) {
971 state.write_u64(self.0);
972 }
973 }
974
975 struct Rng(u64);
976 impl Rng {
977 fn next(&mut self) -> u64 {
978 let mut x = self.0;
979 x ^= x << 13;
980 x ^= x >> 7;
981 x ^= x << 17;
982 self.0 = x;
983 x
984 }
985 }
986
987 #[test]
988 fn persistent_operations_and_mutable_round_trip_preserve_metadata() {
989 let map = Standard::new()
990 .assoc_value("a", 1)
991 .with_meta(Some(crate::lang::data::Metadata::document("doc")));
992 assert_eq!(
993 map.assoc_value("b", 2).meta().map(|m| m.doc().unwrap()),
994 Some("doc")
995 );
996 assert_eq!(
997 map.dissoc_value(&"a").meta().map(|m| m.doc().unwrap()),
998 Some("doc")
999 );
1000 assert_eq!(map.empty().meta().map(|m| m.doc().unwrap()), Some("doc"));
1001 let mut mutable = map.to_mutable();
1002 mutable.assoc("b", 2);
1003 assert_eq!(
1004 mutable.to_persistent().meta().map(|m| m.doc().unwrap()),
1005 Some("doc")
1006 );
1007 }
1008
1009 #[test]
1010 fn assoc_collision_removal_and_persistence() {
1011 let empty = Standard::new();
1012 let a = empty.assoc_value(Collision(1), 10);
1013 let b = a.assoc_value(Collision(2), 20);
1014 let c = b.dissoc_value(&Collision(1));
1015 assert_eq!(a.get(&Collision(1)), Some(&10));
1016 assert_eq!(b.get(&Collision(2)), Some(&20));
1017 assert_eq!(c.get(&Collision(1)), None);
1018 assert_eq!(c.get(&Collision(2)), Some(&20));
1019 assert!(empty.shares_root_with(&empty.dissoc_value(&Collision(9))));
1020 }
1021
1022 #[test]
1023 fn assoc_get_overwrite_and_dissoc_basics() {
1024 let mut map = Standard::new();
1025 for i in 0..100u64 {
1026 map = map.assoc_value(i, i * 10);
1027 }
1028 assert_eq!(map.len(), 100);
1029 for i in 0..100u64 {
1030 assert_eq!(map.get(&i), Some(&(i * 10)));
1031 }
1032 let overwritten = map.assoc_value(42, 999);
1034 assert_eq!(overwritten.len(), 100);
1035 assert_eq!(overwritten.get(&42), Some(&999));
1036 assert_eq!(map.get(&42), Some(&420));
1037 for i in 0..100u64 {
1039 map = map.dissoc_value(&i);
1040 }
1041 assert!(map.is_empty());
1042 assert_eq!(map.get(&0), None);
1043 }
1044
1045 #[test]
1046 fn captured_hash_collision_converts_back_to_single_pair() {
1047 let a = Key(1);
1050 let b = Key(0x1_0000_0001);
1051 let map = Standard::new().assoc_value(a, 10).assoc_value(b, 20);
1052 assert_eq!(map.len(), 2);
1053 assert_eq!(map.get(&a), Some(&10));
1054 assert_eq!(map.get(&b), Some(&20));
1055 let overwritten = map.assoc_value(a, 99);
1057 assert_eq!(overwritten.len(), 2);
1058 assert_eq!(overwritten.get(&a), Some(&99));
1059 assert_eq!(map.get(&a), Some(&10));
1060 let one = map.dissoc_value(&a);
1062 assert_eq!(one.len(), 1);
1063 assert_eq!(one.get(&a), None);
1064 assert_eq!(one.get(&b), Some(&20));
1065 let entries: Vec<_> = one.entries().into_iter().map(|(k, v)| (*k, *v)).collect();
1067 assert_eq!(entries, vec![(b, 20)]);
1068 }
1069
1070 fn churn_build<K: Clone + Eq + Hash + Ord + std::fmt::Debug>(
1074 seed: u64,
1075 mk: impl Fn(u64) -> K,
1076 ) -> (Standard<K, u64>, HashMap<K, u64>) {
1077 let mut rng = Rng(seed);
1078 let mut map = Standard::new();
1079 let mut model = HashMap::new();
1080 for _ in 0..300 {
1081 let key = mk(rng.next() % 24);
1082 if rng.next() % 3 == 0 {
1083 map = map.dissoc_value(&key);
1084 model.remove(&key);
1085 } else {
1086 let value = rng.next();
1087 map = map.assoc_value(key.clone(), value);
1088 model.insert(key, value);
1089 }
1090 }
1091 (map, model)
1092 }
1093
1094 fn churn_case<K: Clone + Eq + Hash + Ord + std::fmt::Debug>(mk: impl Fn(u64) -> K + Copy) {
1095 let (map, model) = churn_build(0x9e37_79b9_7f4a_7c15, mk);
1096 assert_eq!(map.len(), model.len());
1097 for (k, v) in &model {
1098 assert_eq!(map.get(k), Some(v));
1099 }
1100 let mut got: Vec<(K, u64)> = map
1101 .entries()
1102 .into_iter()
1103 .map(|(k, v)| (k.clone(), *v))
1104 .collect();
1105 let mut want: Vec<(K, u64)> = model.iter().map(|(k, v)| (k.clone(), *v)).collect();
1106 got.sort();
1107 want.sort();
1108 assert_eq!(got, want);
1109 let (again, _) = churn_build(0x9e37_79b9_7f4a_7c15, mk);
1111 let got_again: Vec<(K, u64)> = again
1112 .entries()
1113 .into_iter()
1114 .map(|(k, v)| (k.clone(), *v))
1115 .collect();
1116 let got_unsorted: Vec<(K, u64)> = map
1117 .entries()
1118 .into_iter()
1119 .map(|(k, v)| (k.clone(), *v))
1120 .collect();
1121 assert_eq!(got_unsorted, got_again);
1122 }
1123
1124 #[test]
1125 fn churn_matches_hashmap_model() {
1126 churn_case(|i| i as i64);
1127 churn_case(Key);
1128 }
1129
1130 #[test]
1131 fn transient_bulk_assoc_matches_persistent_build() {
1132 let mut rng = Rng(42);
1133 let mut mutable = Standard::new().to_mutable();
1134 let mut persistent = Standard::new();
1135 for _ in 0..1000 {
1136 let key = rng.next() % 500;
1137 let value = rng.next();
1138 mutable.assoc(key, value);
1139 persistent = persistent.assoc_value(key, value);
1140 }
1141 let frozen = mutable.to_persistent();
1142 assert_eq!(frozen.len(), persistent.len());
1143 let transient_entries: Vec<_> = frozen
1145 .entries()
1146 .into_iter()
1147 .map(|(k, v)| (*k, *v))
1148 .collect();
1149 let persistent_entries: Vec<_> = persistent
1150 .entries()
1151 .into_iter()
1152 .map(|(k, v)| (*k, *v))
1153 .collect();
1154 assert_eq!(transient_entries, persistent_entries);
1155 let mut check = Standard::new();
1157 let mut rng = Rng(42);
1158 let mut expected_len = 0;
1159 let mut seen = HashMap::new();
1160 for _ in 0..1000 {
1161 let key = rng.next() % 500;
1162 let value = rng.next();
1163 if seen.insert(key, value).is_none() {
1164 expected_len += 1;
1165 }
1166 check = check.assoc_value(key, value);
1167 }
1168 assert_eq!(check.len(), expected_len);
1169 }
1170
1171 #[test]
1172 fn transient_assoc_dissoc_cycles_stay_correct() {
1173 let mut m = Standard::new().to_mutable();
1174 for round in 0..50u64 {
1175 for i in 0..20u64 {
1176 m.assoc(round * 20 + i, i);
1177 }
1178 for i in 0..20u64 {
1179 m.dissoc(&(round * 20 + i));
1180 }
1181 assert_eq!(m.len(), 0);
1182 }
1183 for i in 0..100u64 {
1184 m.assoc(i, i * 2);
1185 }
1186 for i in (0..100u64).step_by(2) {
1187 m.dissoc(&i);
1188 }
1189 assert_eq!(m.len(), 50);
1190 let frozen = m.to_persistent();
1191 assert_eq!(frozen.len(), 50);
1192 for i in (1..100u64).step_by(2) {
1193 assert_eq!(frozen.get(&i), Some(&(i * 2)));
1194 }
1195 let smaller = frozen.dissoc_value(&1);
1197 assert_eq!(smaller.len(), 49);
1198 assert_eq!(frozen.len(), 50);
1199 assert_eq!(frozen.get(&1), Some(&2));
1200 }
1201
1202 #[test]
1203 fn integer_churn_matches_java_champ_order() {
1204 let mut map = Standard::new();
1205 for i in 0..30i64 {
1206 map = map.assoc_value(Value::Number(i), i);
1207 }
1208 for i in (0..30i64).step_by(3) {
1209 map = map.dissoc_value(&Value::Number(i));
1210 }
1211 let entries: Vec<_> = map
1212 .entries()
1213 .into_iter()
1214 .map(|(k, _)| match k {
1215 Value::Number(value) => *value,
1216 other => panic!("unexpected key: {other:?}"),
1217 })
1218 .collect();
1219 assert_eq!(
1220 entries,
1221 vec![29, 28, 26, 25, 23, 22, 20, 19, 17, 16, 14, 13, 11, 10, 8, 7, 5, 4, 2, 1]
1222 );
1223 }
1224
1225 #[test]
1226 #[should_panic(expected = "mutable map used after to_persistent")]
1227 fn use_after_to_persistent_panics() {
1228 let mut m = Standard::new().to_mutable();
1229 m.assoc(1u64, 1u64);
1230 let _ = m.to_persistent();
1231 m.assoc(2u64, 2u64);
1232 }
1233}