1use std::collections::{BTreeMap, VecDeque};
23use std::ops::Bound;
24use std::sync::{Arc, Mutex, OnceLock};
25
26#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
28pub enum Key {
29 Int(i128),
30 Big(Vec<u64>),
32 Str(Vec<u8>),
33}
34
35#[derive(Clone, Debug)]
36enum Data {
37 Seq { stride: usize, words: VecDeque<u64> },
39 Map(BTreeMap<Key, Box<[u64]>>, Option<Box<[u64]>>),
42}
43
44impl Data {
45 fn len(&self) -> usize {
46 match self {
47 Data::Seq { stride, words } => words.len() / (*stride).max(1),
48 Data::Map(m, _) => m.len(),
49 }
50 }
51}
52
53struct Held {
70 data: Data,
71 objs: bool,
72 key_objs: bool,
73}
74
75impl Held {
76 fn each_handle(&self, with_default: bool, mut f: impl FnMut(u64)) {
79 if !self.objs {
80 return;
81 }
82 match &self.data {
83 Data::Seq { stride, words } => {
84 words.iter().step_by((*stride).max(1)).for_each(|&w| f(w))
85 }
86 Data::Map(m, dflt) => {
87 m.values()
88 .chain(dflt.iter().filter(|_| with_default))
89 .filter_map(|v| v.first().copied())
90 .for_each(f);
91 }
92 }
93 }
94
95 fn each_key(&self, mut f: impl FnMut(u64)) {
97 if !self.key_objs {
98 return;
99 }
100 if let Data::Map(m, _) = &self.data {
101 for k in m.keys() {
102 if let Key::Int(v) = k {
103 f(*v as u64);
104 }
105 }
106 }
107 }
108
109 fn release_elements(&self) {
112 self.each_handle(false, crate::objects::release);
113 }
114}
115
116impl Clone for Held {
117 fn clone(&self) -> Held {
118 self.each_handle(true, crate::objects::retain);
119 self.each_key(crate::objects::retain);
120 Held {
121 data: self.data.clone(),
122 objs: self.objs,
123 key_objs: self.key_objs,
124 }
125 }
126}
127
128impl Drop for Held {
129 fn drop(&mut self) {
130 self.each_handle(true, crate::objects::release);
131 self.each_key(crate::objects::release);
132 }
133}
134
135struct Entry {
136 version: u32,
137 data: Arc<Held>,
138 cursor: Option<(usize, Key)>,
140 frozen: bool,
144}
145
146#[derive(Default)]
147struct Table {
148 entries: Vec<Option<Entry>>,
150 versions: Vec<u32>,
152 free: Vec<u32>,
153 refs: Vec<Option<ElemRef>>,
157 free_refs: Vec<u32>,
158 n_refs: usize,
159}
160
161#[derive(Clone)]
167struct ElemRef {
168 entry: usize,
169 index: i64,
170 key: Option<Key>,
174 live: bool,
175}
176
177fn table() -> &'static Mutex<Table> {
178 static T: OnceLock<Mutex<Table>> = OnceLock::new();
179 T.get_or_init(|| {
180 Mutex::new(Table {
181 entries: vec![None],
182 versions: vec![0],
183 free: Vec::new(),
184 refs: Vec::new(),
185 free_refs: Vec::new(),
186 n_refs: 0,
187 })
188 })
189}
190
191fn index(h: u64) -> usize {
192 (h & 0xffff_ffff) as usize
193}
194
195impl Table {
196 fn held(&self, h: u64) -> Option<&Held> {
197 self.entries.get(index(h))?.as_ref().map(|e| &*e.data)
198 }
199
200 fn data(&self, h: u64) -> Option<&Data> {
201 self.held(h).map(|e| &e.data)
202 }
203
204 fn alloc(&mut self, data: Held) -> u64 {
205 let i = match self.free.pop() {
206 Some(i) => i as usize,
207 None => {
208 self.entries.push(None);
209 self.versions.push(0);
210 self.entries.len() - 1
211 }
212 };
213 let version = self.versions[i].wrapping_add(1);
214 self.versions[i] = version;
215 self.entries[i] = Some(Entry {
216 version,
217 data: Arc::new(data),
218 cursor: None,
219 frozen: false,
220 });
221 (u64::from(version) << 32) | i as u64
222 }
223
224 fn release(&mut self, h: u64) {
228 let i = index(h);
229 if i != 0
230 && self.entries.get(i).is_some_and(|e| {
231 e.as_ref()
232 .is_some_and(|e| !e.frozen && u64::from(e.version) == h >> 32)
233 })
234 {
235 self.refs_outdated(i, 0);
236 self.entries[i] = None;
237 self.free.push(i as u32);
238 }
239 }
240
241 fn refs_outdated(&mut self, entry: usize, from: i64) {
244 if self.n_refs == 0 {
245 return;
246 }
247 for r in self.refs.iter_mut().flatten() {
248 if r.live && r.entry == entry && r.index >= from {
249 r.live = false;
250 }
251 }
252 }
253
254 fn refs_key_removed(&mut self, entry: usize, key: &Key) {
258 if self.n_refs == 0 {
259 return;
260 }
261 for r in self.refs.iter_mut().flatten() {
262 if r.live && r.entry == entry && r.key.as_ref() == Some(key) {
263 r.live = false;
264 }
265 }
266 }
267
268 fn refs_removed(&mut self, entry: usize, i: i64) {
271 if self.n_refs == 0 {
272 return;
273 }
274 for rr in self.refs.iter_mut().flatten() {
275 if !rr.live || rr.entry != entry || rr.index < i {
276 continue;
277 }
278 if rr.index == i {
279 rr.live = false;
280 } else {
281 rr.index -= 1;
282 }
283 }
284 }
285
286 fn refs_inserted(&mut self, entry: usize, i: i64) {
289 if self.n_refs == 0 {
290 return;
291 }
292 for r in self.refs.iter_mut().flatten() {
293 if r.live && r.entry == entry && r.index >= i {
294 r.index += 1;
295 }
296 }
297 }
298
299 fn refs_moved(&mut self, from: usize, to: usize) {
302 if self.n_refs == 0 {
303 return;
304 }
305 for r in self.refs.iter_mut().flatten() {
306 if r.live && r.entry == from {
307 r.entry = to;
308 }
309 }
310 }
311
312 fn modify(&mut self, h: u64, empty: impl FnOnce() -> Held, f: impl FnOnce(&mut Held)) -> u64 {
315 let i = index(h);
316 match self.entries.get_mut(i).and_then(|e| e.as_mut()) {
317 Some(e) if e.frozen => {
318 let mut d = (*e.data).clone();
319 f(&mut d);
320 let new = self.alloc(d);
321 self.refs_moved(i, index(new));
322 new
323 }
324 Some(e) if i != 0 => {
325 f(Arc::make_mut(&mut e.data));
326 e.version = e.version.wrapping_add(1);
327 e.cursor = None;
328 self.versions[i] = e.version;
329 (u64::from(e.version) << 32) | i as u64
330 }
331 _ => {
332 let mut d = empty();
333 f(&mut d);
334 self.alloc(d)
335 }
336 }
337 }
338}
339
340#[derive(Clone, Copy, Debug)]
343pub struct Shape {
344 pub elem_words: usize,
345 pub assoc: bool,
346 pub key: KeyKind,
347 pub obj: bool,
350}
351
352#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
354pub enum KeyKind {
355 Int {
357 width: u32,
358 signed: bool,
359 },
360 Str,
361 Obj,
364}
365
366impl Shape {
367 fn empty(&self) -> Held {
368 self.held(if self.assoc {
369 Data::Map(BTreeMap::new(), None)
370 } else {
371 Data::Seq {
372 stride: self.elem_words.max(1),
373 words: VecDeque::new(),
374 }
375 })
376 }
377
378 fn held(&self, data: Data) -> Held {
379 Held {
380 data,
381 objs: self.obj,
382 key_objs: self.key == KeyKind::Obj,
383 }
384 }
385
386 pub fn discard(&self, val: &[u64]) {
390 if self.obj
391 && let Some(&w) = val.first()
392 {
393 crate::objects::release(w);
394 }
395 }
396
397 pub fn key_from_bits(&self, bits: &[u64]) -> Option<Key> {
400 match self.key {
401 KeyKind::Str => Some(Key::Str(crate::strings::bytes(bits[0]).to_vec())),
402 KeyKind::Int { .. } | KeyKind::Obj => {
403 let (width, signed) = if let KeyKind::Int { width, signed } = self.key {
404 (width, signed)
405 } else {
406 (64, false)
408 };
409 let w = width as usize;
410 let bit = |i: usize| (bits.get(i / 64).copied().unwrap_or(0) >> (i % 64)) & 1;
411 if (w..2 * w).any(|i| bit(i) != 0) {
412 return None;
413 }
414 if w <= 127 {
415 let mut v: i128 = 0;
416 for i in 0..w {
417 v |= (bit(i) as i128) << i;
418 }
419 if signed && w > 0 && bit(w - 1) == 1 {
420 v -= 1i128 << w;
421 }
422 Some(Key::Int(v))
423 } else {
424 let n = w.div_ceil(64);
425 let mut words = vec![0u64; n];
426 for i in 0..w {
427 words[i / 64] |= bit(i) << (i % 64);
428 }
429 words.reverse();
430 Some(Key::Big(words))
431 }
432 }
433 }
434 }
435
436 pub fn key_to_bits(&self, key: &Key, out: &mut [u64]) {
438 out.fill(0);
439 match key {
440 Key::Str(s) => out[0] = crate::strings::intern(s),
441 Key::Int(v) => {
442 let width = match self.key {
443 KeyKind::Int { width, .. } => width,
444 KeyKind::Obj => 64,
445 KeyKind::Str => return,
446 };
447 for i in 0..width as usize {
448 if (v >> i.min(127)) & 1 == 1 {
449 out[i / 64] |= 1 << (i % 64);
450 }
451 }
452 }
453 Key::Big(words) => {
454 for (i, w) in words.iter().rev().enumerate() {
455 if let Some(o) = out.get_mut(i) {
456 *o = *w;
457 }
458 }
459 }
460 }
461 }
462}
463
464pub fn size(h: u64) -> usize {
466 let t = table().lock().unwrap_or_else(|e| e.into_inner());
467 t.data(h).map_or(0, |d| d.len())
468}
469
470pub fn get(h: u64, i: i64, out: &mut [u64]) -> bool {
473 let t = table().lock().unwrap_or_else(|e| e.into_inner());
474 let Some(Data::Seq { stride, words }) = t.data(h) else {
475 return false;
476 };
477 let n = words.len() / stride;
478 if i < 0 || i as usize >= n {
479 return false;
480 }
481 let base = i as usize * stride;
482 for (k, o) in out.iter_mut().enumerate().take(*stride) {
483 *o = words[base + k];
484 }
485 true
486}
487
488pub fn lookup(h: u64, key: &Key, out: &mut [u64]) -> bool {
491 let t = table().lock().unwrap_or_else(|e| e.into_inner());
492 let Some(Data::Map(m, dflt)) = t.data(h) else {
493 return false;
494 };
495 match m.get(key).or(dflt.as_ref()) {
496 Some(v) => {
497 let n = out.len().min(v.len());
498 out[..n].copy_from_slice(&v[..n]);
499 true
500 }
501 None => false,
502 }
503}
504
505pub fn exists(h: u64, key: &Key) -> bool {
507 let t = table().lock().unwrap_or_else(|e| e.into_inner());
508 matches!(t.data(h), Some(Data::Map(m, _)) if m.contains_key(key))
509}
510
511pub fn set(shape: &Shape, h: u64, i: i64, val: &[u64], queue: bool) -> u64 {
518 let n = size(h) as i64;
519 if i < 0 || i > n || (i == n && !queue) {
520 shape.discard(val);
521 return h;
522 }
523 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
524 t.modify(
525 h,
526 || shape.empty(),
527 |d| {
528 let Held { data, objs, .. } = d;
529 if let Data::Seq { stride, words } = data {
530 let base = i as usize * *stride;
531 if base == words.len() {
532 words.extend(val.iter().copied().take(*stride));
533 words.resize(base + *stride, 0);
534 } else {
535 if *objs {
536 crate::objects::release(words[base]);
537 }
538 for k in 0..*stride {
539 words[base + k] = val.get(k).copied().unwrap_or(0);
540 }
541 }
542 }
543 },
544 )
545}
546
547pub fn store(shape: &Shape, h: u64, key: Key, val: &[u64]) -> u64 {
550 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
551 let v: Box<[u64]> = val[..shape.elem_words.min(val.len())].into();
552 t.modify(
553 h,
554 || shape.empty(),
555 |d| {
556 let Held {
557 data,
558 objs,
559 key_objs,
560 } = d;
561 if let Data::Map(m, _) = data {
562 if *key_objs
564 && !m.contains_key(&key)
565 && let Key::Int(k) = &key
566 {
567 crate::objects::retain(*k as u64);
568 }
569 if let Some(old) = m.insert(key, v)
570 && *objs
571 && let Some(&w) = old.first()
572 {
573 crate::objects::release(w);
574 }
575 }
576 },
577 )
578}
579
580pub fn insert(shape: &Shape, h: u64, i: i64, val: &[u64]) -> u64 {
584 let n = size(h) as i64;
585 if i < 0 || i > n {
586 shape.discard(val);
587 return h;
588 }
589 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
590 let new = t.modify(
591 h,
592 || shape.empty(),
593 |d| {
594 if let Data::Seq { stride, words } = &mut d.data {
595 let at = i as usize * *stride;
596 for k in (0..*stride).rev() {
597 words.insert(at, val.get(k).copied().unwrap_or(0));
598 }
599 }
600 },
601 );
602 t.refs_inserted(index(new), i);
603 new
604}
605
606pub fn push(shape: &Shape, h: u64, val: &[u64], front: bool) -> u64 {
608 if front {
609 insert(shape, h, 0, val)
610 } else {
611 insert(shape, h, size(h) as i64, val)
612 }
613}
614
615pub fn pop(shape: &Shape, h: u64, out: &mut [u64], front: bool) -> (u64, bool) {
619 let n = size(h);
620 if n == 0 {
621 return (h, false);
622 }
623 let i = if front { 0 } else { n - 1 };
624 get(h, i as i64, out);
625 (remove_at(shape, h, i as i64, false), true)
626}
627
628pub fn truncate(shape: &Shape, h: u64, keep: usize) -> u64 {
632 if size(h) <= keep {
633 return h;
634 }
635 eprintln!(
636 "Warning: bounded queue exceeded its bound; elements beyond index {} discarded",
637 keep - 1
638 );
639 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
640 let new = t.modify(
641 h,
642 || shape.empty(),
643 |d| {
644 let Held { data, objs, .. } = d;
645 if let Data::Seq { stride, words } = data {
646 let at = keep * *stride;
647 if *objs {
648 for w in words.iter().skip(at).step_by(*stride) {
649 crate::objects::release(*w);
650 }
651 }
652 words.truncate(at);
653 }
654 },
655 );
656 t.refs_outdated(index(new), keep as i64);
657 new
658}
659
660pub fn delete_at(shape: &Shape, h: u64, i: i64) -> u64 {
663 remove_at(shape, h, i, true)
664}
665
666fn remove_at(shape: &Shape, h: u64, i: i64, release: bool) -> u64 {
669 let n = size(h) as i64;
670 if i < 0 || i >= n {
671 return h;
672 }
673 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
674 let new = t.modify(
675 h,
676 || shape.empty(),
677 |d| {
678 let Held { data, objs, .. } = d;
679 if let Data::Seq { stride, words } = data {
680 let at = i as usize * *stride;
681 if release && *objs {
682 crate::objects::release(words[at]);
683 }
684 words.drain(at..at + *stride);
685 }
686 },
687 );
688 t.refs_removed(index(new), i);
689 new
690}
691
692pub fn delete_key(shape: &Shape, h: u64, key: &Key) -> u64 {
694 if !exists(h, key) {
695 return h;
696 }
697 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
698 let new = t.modify(
699 h,
700 || shape.empty(),
701 |d| {
702 let Held {
703 data,
704 objs,
705 key_objs,
706 } = d;
707 if let Data::Map(m, _) = data
708 && let Some(old) = m.remove(key)
709 {
710 if *key_objs && let Key::Int(k) = key {
711 crate::objects::release(*k as u64);
712 }
713 if *objs && let Some(&w) = old.first() {
714 crate::objects::release(w);
715 }
716 }
717 },
718 );
719 t.refs_key_removed(index(new), key);
720 new
721}
722
723pub fn set_default(shape: &Shape, h: u64, val: &[u64]) -> u64 {
727 let v: Box<[u64]> = val[..shape.elem_words.min(val.len())].into();
728 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
729 t.modify(
730 h,
731 || shape.empty(),
732 |d| {
733 let Held { data, objs, .. } = d;
734 if let Data::Map(_, dflt) = data
735 && let Some(old) = dflt.replace(v)
736 && *objs
737 && let Some(&w) = old.first()
738 {
739 crate::objects::release(w);
740 }
741 },
742 )
743}
744
745pub fn clear(shape: &Shape, h: u64) -> u64 {
747 if h == 0 {
748 return 0;
749 }
750 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
751 let new = t.modify(
752 h,
753 || shape.empty(),
754 |d| {
755 d.release_elements();
756 d.each_key(crate::objects::release);
757 match &mut d.data {
758 Data::Map(m, _) => m.clear(),
759 Data::Seq { words, .. } => words.clear(),
760 }
761 },
762 );
763 t.refs_outdated(index(new), 0);
764 new
765}
766
767pub fn clone(h: u64) -> u64 {
771 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
772 if t.entries
773 .get(index(h))
774 .and_then(|e| e.as_ref())
775 .is_some_and(|e| e.frozen)
776 {
777 return h;
778 }
779 match t.entries.get(index(h)).and_then(|e| e.as_ref()) {
780 Some(e) => {
781 let data = Arc::clone(&e.data);
782 let fresh = t.alloc(Held {
783 data: Data::Map(BTreeMap::new(), None),
784 objs: false,
785 key_objs: false,
786 });
787 if let Some(e) = t.entries[index(fresh)].as_mut() {
788 e.data = data;
789 }
790 fresh
791 }
792 None => 0,
793 }
794}
795
796#[derive(Clone, Debug, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
801pub struct Nest {
802 pub slots: Vec<(u32, Nest)>,
803}
804
805fn bits64(words: &[u64], at: usize) -> u64 {
807 let (w, s) = (at / 64, at % 64);
808 let lo = words.get(w).copied().unwrap_or(0) >> s;
809 if s == 0 {
810 lo
811 } else {
812 lo | (words.get(w + 1).copied().unwrap_or(0) << (64 - s))
813 }
814}
815
816fn set_bits64(words: &mut [u64], at: usize, v: u64) {
817 let (w, s) = (at / 64, at % 64);
818 if s == 0 {
819 if let Some(x) = words.get_mut(w) {
820 *x = v;
821 }
822 return;
823 }
824 if let Some(x) = words.get_mut(w) {
825 *x = (*x & (u64::MAX >> (64 - s))) | (v << s);
826 }
827 if let Some(x) = words.get_mut(w + 1) {
828 *x = (*x & (u64::MAX << s)) | (v >> (64 - s));
829 }
830}
831
832fn elem_list(h: u64) -> Vec<(Option<Key>, Vec<u64>)> {
835 let t = table().lock().unwrap_or_else(|e| e.into_inner());
836 match t.data(h) {
837 None => Vec::new(),
838 Some(Data::Seq { stride, words }) => words
839 .iter()
840 .copied()
841 .collect::<Vec<_>>()
842 .chunks((*stride).max(1))
843 .map(|c| (None, c.to_vec()))
844 .collect(),
845 Some(Data::Map(m, _)) => m
846 .iter()
847 .map(|(k, v)| (Some(k.clone()), v.to_vec()))
848 .collect(),
849 }
850}
851
852pub fn clone_deep(h: u64, nest: &Nest, minted: &mut Vec<u64>) -> u64 {
858 let fresh = clone(h);
859 if fresh != 0 {
860 minted.push(fresh);
861 }
862 if fresh == 0 || nest.slots.is_empty() {
863 return fresh;
864 }
865 let mut inner: Vec<(usize, u64)> = Vec::new();
866 {
867 let t = table().lock().unwrap_or_else(|e| e.into_inner());
868 let Some(e) = t.entries.get(index(fresh)).and_then(|e| e.as_ref()) else {
869 return fresh;
870 };
871 if e.frozen {
872 return fresh;
873 }
874 let mut visit = |el: &[u64]| {
875 for (k, (off, _)) in nest.slots.iter().enumerate() {
876 let x = bits64(el, *off as usize);
877 if x != 0 {
878 inner.push((k, x));
879 }
880 }
881 };
882 match &e.data.data {
883 Data::Seq { stride, words } => words
884 .iter()
885 .copied()
886 .collect::<Vec<_>>()
887 .chunks((*stride).max(1))
888 .for_each(&mut visit),
889 Data::Map(m, d) => m.values().chain(d.iter()).for_each(|v| visit(v)),
890 }
891 }
892 let mut copies: std::collections::HashMap<(usize, u64), u64> = std::collections::HashMap::new();
893 for (k, x) in inner {
894 copies
895 .entry((k, x))
896 .or_insert_with(|| clone_deep(x, &nest.slots[k].1, minted));
897 }
898 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
899 let Some(e) = t.entries.get_mut(index(fresh)).and_then(|e| e.as_mut()) else {
900 return fresh;
901 };
902 let held = Arc::make_mut(&mut e.data);
903 let mut rewrite = |el: &mut [u64]| {
904 for (k, (off, _)) in nest.slots.iter().enumerate() {
905 let x = bits64(el, *off as usize);
906 if let Some(&n) = copies.get(&(k, x)) {
907 set_bits64(el, *off as usize, n);
908 }
909 }
910 };
911 match &mut held.data {
912 Data::Seq { stride, words } => words
913 .make_contiguous()
914 .chunks_mut((*stride).max(1))
915 .for_each(&mut rewrite),
916 Data::Map(m, d) => m
917 .values_mut()
918 .map(|v| &mut v[..])
919 .chain(d.iter_mut().map(|v| &mut v[..]))
920 .for_each(rewrite),
921 }
922 fresh
923}
924
925pub fn equal_nest(a: u64, b: u64, nest: &Nest) -> bool {
929 if nest.slots.is_empty() {
930 return equal(a, b);
931 }
932 let (x, y) = (elem_list(a), elem_list(b));
933 x.len() == y.len()
934 && x.iter().zip(&y).all(|((ka, ea), (kb, eb))| {
935 if ka != kb || ea.len() != eb.len() {
936 return false;
937 }
938 let (mut ea, mut eb) = (ea.clone(), eb.clone());
939 let mut same = true;
940 for (off, sub) in &nest.slots {
941 let at = *off as usize;
942 same &= equal_nest(bits64(&ea, at), bits64(&eb, at), sub);
943 set_bits64(&mut ea, at, 0);
944 set_bits64(&mut eb, at, 0);
945 }
946 same && ea == eb
947 })
948}
949
950pub fn live_count() -> usize {
953 let t = table().lock().unwrap_or_else(|e| e.into_inner());
954 t.entries.iter().filter(|e| e.is_some()).count()
955}
956
957pub fn release(h: u64) {
959 table().lock().unwrap_or_else(|e| e.into_inner()).release(h);
960}
961
962pub fn ref_open(h: u64, i: i64) -> u64 {
970 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
971 let e = index(h);
972 let n = t.data(h).filter(|_| e != 0).map_or(0, |d| d.len() as i64);
973 if i < 0 || i >= n {
974 return 0;
975 }
976 t.ref_push(ElemRef {
977 entry: e,
978 index: i,
979 key: None,
980 live: true,
981 })
982}
983
984pub fn ref_open_key(h: u64, key: Key) -> u64 {
991 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
992 let e = index(h);
993 if e == 0 || !matches!(t.data(h), Some(Data::Map(..))) {
994 return 0;
995 }
996 t.ref_push(ElemRef {
997 entry: e,
998 index: 0,
999 key: Some(key),
1000 live: true,
1001 })
1002}
1003
1004impl Table {
1005 fn ref_push(&mut self, rec: ElemRef) -> u64 {
1006 let rec = Some(rec);
1007 self.n_refs += 1;
1008 match self.free_refs.pop() {
1009 Some(k) => {
1010 self.refs[k as usize] = rec;
1011 u64::from(k) + 1
1012 }
1013 None => {
1014 self.refs.push(rec);
1015 self.refs.len() as u64
1016 }
1017 }
1018 }
1019}
1020
1021pub fn ref_own(shape: &Shape, h: u64) -> u64 {
1025 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
1026 if h == 0 {
1027 return if shape.assoc {
1029 t.modify(h, || shape.empty(), |_| {})
1030 } else {
1031 0
1032 };
1033 }
1034 if t.entries
1035 .get(index(h))
1036 .and_then(|e| e.as_ref())
1037 .is_some_and(|e| e.frozen)
1038 {
1039 t.modify(h, || shape.empty(), |_| {})
1040 } else {
1041 h
1042 }
1043}
1044
1045fn ref_rec(t: &Table, id: u64) -> Option<ElemRef> {
1046 t.refs.get(id.wrapping_sub(1) as usize).cloned().flatten()
1047}
1048
1049pub fn ref_get(id: u64, out: &mut [u64]) -> bool {
1053 let t = table().lock().unwrap_or_else(|e| e.into_inner());
1054 let Some(r) = ref_rec(&t, id).filter(|r| r.live) else {
1055 return false;
1056 };
1057 match (&r.key, t.data(r.entry as u64)) {
1058 (Some(key), Some(Data::Map(m, dflt))) => match m.get(key).or(dflt.as_ref()) {
1059 Some(v) => {
1060 let n = out.len().min(v.len());
1061 out[..n].copy_from_slice(&v[..n]);
1062 true
1063 }
1064 None => false,
1065 },
1066 (None, _) => {
1067 drop(t);
1068 get(r.entry as u64, r.index, out)
1069 }
1070 _ => false,
1071 }
1072}
1073
1074pub fn ref_put(id: u64, val: &[u64]) {
1079 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
1080 let Some(r) = ref_rec(&t, id).filter(|r| r.live) else {
1081 return;
1082 };
1083 let Some(e) = t.entries.get_mut(r.entry).and_then(|e| e.as_mut()) else {
1084 return;
1085 };
1086 let held = Arc::make_mut(&mut e.data);
1087 let key_objs = held.key_objs;
1088 match (&mut held.data, r.key) {
1089 (Data::Seq { stride, words }, None) => {
1090 let base = r.index as usize * *stride;
1091 if base + *stride <= words.len() {
1092 for k in 0..*stride {
1093 words[base + k] = val.get(k).copied().unwrap_or(0);
1094 }
1095 e.cursor = None;
1096 }
1097 }
1098 (Data::Map(m, _), Some(key)) => {
1099 match m.get_mut(&key) {
1100 Some(slot) => {
1101 let n = slot.len().min(val.len());
1102 slot[..n].copy_from_slice(&val[..n]);
1103 }
1104 None => {
1105 if key_objs && let Key::Int(k) = &key {
1106 crate::objects::retain(*k as u64);
1107 }
1108 m.insert(key, val.into());
1109 }
1110 }
1111 e.cursor = None;
1112 }
1113 _ => {}
1114 }
1115}
1116
1117fn bit_at(w: &[u64], i: usize) -> bool {
1118 w.get(i / 64).is_some_and(|x| (x >> (i % 64)) & 1 != 0)
1119}
1120
1121fn set_bit(w: &mut [u64], i: usize, v: bool) {
1122 if let Some(x) = w.get_mut(i / 64) {
1123 let m = 1u64 << (i % 64);
1124 *x = if v { *x | m } else { *x & !m };
1125 }
1126}
1127
1128pub fn ref_get_part(id: u64, lo: u64, w: u32, big_w: u32, out: &mut [u64]) -> bool {
1135 if crate::winref::is_window(id) {
1136 return crate::winref::get_part(id, lo, w, big_w, out);
1137 }
1138 if big_w == 0 {
1139 return ref_get(id, out);
1140 }
1141 let mut elem = vec![0u64; (2 * big_w as usize).div_ceil(64)];
1142 if !ref_get(id, &mut elem) {
1143 return false;
1144 }
1145 out.fill(0);
1146 for k in 0..w as usize {
1147 let i = lo as usize + k;
1150 if i < big_w as usize {
1151 set_bit(out, k, bit_at(&elem, i));
1152 set_bit(out, w as usize + k, bit_at(&elem, big_w as usize + i));
1153 }
1154 }
1155 true
1156}
1157
1158pub fn ref_put_part(id: u64, lo: u64, w: u32, big_w: u32, val: &[u64]) {
1164 if crate::winref::is_window(id) {
1165 return crate::winref::put_part(id, lo, w, big_w, val);
1166 }
1167 if big_w == 0 {
1168 return ref_put(id, val);
1169 }
1170 let mut elem = vec![0u64; (2 * big_w as usize).div_ceil(64)];
1171 if !ref_get(id, &mut elem) {
1172 return;
1173 }
1174 for k in 0..w as usize {
1175 let i = lo as usize + k;
1176 if i < big_w as usize {
1177 set_bit(&mut elem, i, bit_at(val, k));
1178 set_bit(&mut elem, big_w as usize + i, bit_at(val, w as usize + k));
1179 }
1180 }
1181 ref_put(id, &elem);
1182}
1183
1184pub fn ref_close(id: u64) {
1186 if crate::winref::is_window(id) {
1187 return crate::winref::close(id);
1188 }
1189 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
1190 let k = id.wrapping_sub(1) as usize;
1191 if t.refs.get_mut(k).and_then(Option::take).is_some() {
1192 t.free_refs.push(k as u32);
1193 t.n_refs -= 1;
1194 }
1195}
1196
1197#[cfg(test)]
1203pub(crate) fn is_live(h: u64) -> bool {
1204 let t = table().lock().unwrap_or_else(|e| e.into_inner());
1205 t.entries
1206 .get(index(h))
1207 .and_then(|e| e.as_ref())
1208 .is_some_and(|e| u64::from(e.version) == h >> 32)
1209}
1210
1211pub fn resized(shape: &Shape, src: u64, n: usize, dflt: &[u64]) -> u64 {
1215 let stride = shape.elem_words.max(1);
1216 let mut words = VecDeque::with_capacity(n * stride);
1217 {
1218 let t = table().lock().unwrap_or_else(|e| e.into_inner());
1219 if let Some(Data::Seq { words: w, .. }) = t.data(src) {
1220 words.extend(w.iter().copied().take(n * stride));
1221 }
1222 }
1223 while words.len() < n * stride {
1224 for k in 0..stride {
1225 words.push_back(dflt.get(k).copied().unwrap_or(0));
1226 }
1227 }
1228 retain_elems(shape, words.iter().copied());
1229 table()
1230 .lock()
1231 .unwrap_or_else(|e| e.into_inner())
1232 .alloc(shape.held(Data::Seq { stride, words }))
1233}
1234
1235fn retain_elems(shape: &Shape, words: impl Iterator<Item = u64>) {
1238 if shape.obj {
1239 words
1240 .step_by(shape.elem_words.max(1))
1241 .for_each(crate::objects::retain);
1242 }
1243}
1244
1245pub fn from_words(shape: &Shape, elems: &[u64]) -> u64 {
1248 let stride = shape.elem_words.max(1);
1249 table()
1250 .lock()
1251 .unwrap_or_else(|e| e.into_inner())
1252 .alloc(shape.held(Data::Seq {
1253 stride,
1254 words: elems.iter().copied().collect(),
1255 }))
1256}
1257
1258pub fn from_copies(shape: &Shape, elems: &[u64]) -> u64 {
1261 retain_elems(shape, elems.iter().copied());
1262 from_words(shape, elems)
1263}
1264
1265pub fn frozen_from_words(elem_words: usize, elems: &[u64]) -> u64 {
1268 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
1269 let h = t.alloc(Held {
1270 data: Data::Seq {
1271 stride: elem_words.max(1),
1272 words: elems.iter().copied().collect(),
1273 },
1274 objs: false,
1275 key_objs: false,
1276 });
1277 if let Some(e) = t.entries[index(h)].as_mut() {
1278 e.frozen = true;
1279 }
1280 h
1281}
1282
1283pub fn frozen_map(entries: Vec<(Key, Vec<u64>)>, default: Option<Vec<u64>>) -> u64 {
1286 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
1287 let h = t.alloc(Held {
1288 data: Data::Map(
1289 entries.into_iter().map(|(k, v)| (k, v.into())).collect(),
1290 default.map(Into::into),
1291 ),
1292 objs: false,
1293 key_objs: false,
1294 });
1295 if let Some(e) = t.entries[index(h)].as_mut() {
1296 e.frozen = true;
1297 }
1298 h
1299}
1300
1301#[derive(Clone, Debug, PartialEq, Eq)]
1303pub enum FrozenData {
1304 Seq {
1305 stride: usize,
1306 words: Vec<u64>,
1307 },
1308 Map {
1309 entries: Vec<(Key, Vec<u64>)>,
1310 default: Option<Vec<u64>>,
1311 },
1312}
1313
1314pub fn frozen_snapshot() -> Result<Vec<FrozenData>, String> {
1321 let t = table().lock().unwrap_or_else(|e| e.into_inner());
1322 t.entries[1..]
1323 .iter()
1324 .enumerate()
1325 .map(|(i, e)| {
1326 let Some(e) = e.as_ref().filter(|e| e.frozen && e.version == 1) else {
1327 return Err(format!(
1328 "collection {} is not a constant of a declaration's initial value",
1329 i + 1
1330 ));
1331 };
1332 Ok(plain(e))
1333 })
1334 .collect()
1335}
1336
1337fn plain(e: &Entry) -> FrozenData {
1338 match &e.data.data {
1339 Data::Seq { stride, words } => FrozenData::Seq {
1340 stride: *stride,
1341 words: words.iter().copied().collect(),
1342 },
1343 Data::Map(m, dflt) => FrozenData::Map {
1344 entries: m.iter().map(|(k, v)| (k.clone(), v.to_vec())).collect(),
1345 default: dflt.as_ref().map(|d| d.to_vec()),
1346 },
1347 }
1348}
1349
1350pub fn frozen_preload(frozen: &[FrozenData]) -> Result<(), String> {
1354 for (i, f) in frozen.iter().enumerate() {
1355 let want = (1u64 << 32) | (i as u64 + 1);
1356 let have = frozen_snapshot_entry(i + 1);
1357 if let Some(have) = have {
1358 if &have != f {
1359 return Err(format!(
1360 "collection {} of the design cannot take its handle: this process \
1361 already made a different one",
1362 i + 1
1363 ));
1364 }
1365 continue;
1366 }
1367 let got = match f {
1368 FrozenData::Seq { stride, words } => frozen_from_words(*stride, words),
1369 FrozenData::Map { entries, default } => frozen_map(entries.clone(), default.clone()),
1370 };
1371 if got != want {
1372 return Err(format!(
1373 "collection {} of the design got handle {got:#x}, not {want:#x}",
1374 i + 1
1375 ));
1376 }
1377 }
1378 Ok(())
1379}
1380
1381fn frozen_snapshot_entry(i: usize) -> Option<FrozenData> {
1383 let t = table().lock().unwrap_or_else(|e| e.into_inner());
1384 t.entries.get(i)?.as_ref().filter(|e| e.frozen).map(plain)
1385}
1386
1387pub fn map_with_values(h: u64, elem_words: usize, flat: &[u64]) -> Option<u64> {
1394 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
1395 let Some(Data::Map(m, dflt)) = t.data(h) else {
1396 return None;
1397 };
1398 if flat.len() != m.len() * elem_words {
1399 return None;
1400 }
1401 let keys: Vec<Key> = m.keys().cloned().collect();
1402 let dflt = dflt.clone();
1403 let map: BTreeMap<Key, Box<[u64]>> = keys
1404 .into_iter()
1405 .zip(flat.chunks(elem_words.max(1)))
1406 .map(|(k, v)| (k, v.into()))
1407 .collect();
1408 Some(t.alloc(Held {
1409 data: Data::Map(map, dflt),
1410 objs: false,
1411 key_objs: false,
1412 }))
1413}
1414
1415pub fn append(shape: &Shape, h: u64, other: u64) -> u64 {
1418 let extra: Vec<u64> = {
1419 let t = table().lock().unwrap_or_else(|e| e.into_inner());
1420 match t.data(other) {
1421 Some(Data::Seq { words, .. }) => words.iter().copied().collect(),
1422 _ => Vec::new(),
1423 }
1424 };
1425 retain_elems(shape, extra.iter().copied());
1426 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
1427 t.modify(
1428 h,
1429 || shape.empty(),
1430 |d| {
1431 if let Data::Seq { words, .. } = &mut d.data {
1432 words.extend(extra);
1433 }
1434 },
1435 )
1436}
1437
1438pub fn slice(shape: &Shape, h: u64, a: i64, b: i64) -> u64 {
1441 let n = size(h) as i64;
1442 let a = a.max(0);
1443 let b = b.min(n - 1);
1444 let stride = shape.elem_words.max(1);
1445 let mut out = VecDeque::new();
1446 if a <= b {
1447 let t = table().lock().unwrap_or_else(|e| e.into_inner());
1448 if let Some(Data::Seq { words, .. }) = t.data(h) {
1449 out.extend(
1450 words
1451 .range(a as usize * stride..(b as usize + 1) * stride)
1452 .copied(),
1453 );
1454 }
1455 }
1456 retain_elems(shape, out.iter().copied());
1457 table()
1458 .lock()
1459 .unwrap_or_else(|e| e.into_inner())
1460 .alloc(shape.held(Data::Seq { stride, words: out }))
1461}
1462
1463pub fn equal(a: u64, b: u64) -> bool {
1465 let t = table().lock().unwrap_or_else(|e| e.into_inner());
1466 match (t.data(a), t.data(b)) {
1467 (None, None) => true,
1468 (Some(d), None) | (None, Some(d)) => d.len() == 0,
1469 (Some(Data::Seq { words: x, .. }), Some(Data::Seq { words: y, .. })) => x == y,
1470 (Some(Data::Map(x, _)), Some(Data::Map(y, _))) => x == y,
1471 _ => false,
1472 }
1473}
1474
1475pub fn neighbor(h: u64, key: Option<&Key>, forward: bool) -> Option<Key> {
1478 let t = table().lock().unwrap_or_else(|e| e.into_inner());
1479 let Some(Data::Map(m, _)) = t.data(h) else {
1480 return None;
1481 };
1482 let found = match (key, forward) {
1483 (None, true) => m.keys().next(),
1484 (None, false) => m.keys().next_back(),
1485 (Some(k), true) => m
1486 .range((Bound::Excluded(k.clone()), Bound::Unbounded))
1487 .next()
1488 .map(|(k, _)| k),
1489 (Some(k), false) => m
1490 .range((Bound::Unbounded, Bound::Excluded(k.clone())))
1491 .next_back()
1492 .map(|(k, _)| k),
1493 };
1494 found.cloned()
1495}
1496
1497pub fn key_at(h: u64, pos: usize) -> Option<Key> {
1500 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
1501 let i = index(h);
1502 let e = t.entries.get_mut(i)?.as_mut()?;
1503 let Data::Map(m, _) = &e.data.data else {
1504 return None;
1505 };
1506 let key = match &e.cursor {
1507 Some((p, k)) if *p == pos => Some(k.clone()),
1508 Some((p, k)) if *p + 1 == pos => m
1509 .range((Bound::Excluded(k.clone()), Bound::Unbounded))
1510 .next()
1511 .map(|(k, _)| k.clone()),
1512 _ => m.keys().nth(pos).cloned(),
1513 };
1514 if let Some(k) = &key {
1515 e.cursor = Some((pos, k.clone()));
1516 }
1517 key
1518}
1519
1520pub fn entry_at(h: u64, pos: usize, out: &mut [u64]) -> Option<Key> {
1523 let key = key_at(h, pos)?;
1524 lookup(h, &key, out);
1525 Some(key)
1526}
1527
1528pub fn permute(shape: &Shape, h: u64, order: &[usize]) -> u64 {
1531 let old = elements(h);
1532 if old.len() != order.len() || old.is_empty() {
1533 return h;
1534 }
1535 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
1536 let new = t.modify(
1537 h,
1538 || shape.empty(),
1539 |d| {
1540 if let Data::Seq { words, .. } = &mut d.data {
1542 words.clear();
1543 for &k in order {
1544 words.extend(old[k].iter().copied());
1545 }
1546 }
1547 },
1548 );
1549 t.refs_outdated(index(new), 0);
1554 new
1555}
1556
1557pub fn elements(h: u64) -> Vec<Vec<u64>> {
1560 let t = table().lock().unwrap_or_else(|e| e.into_inner());
1561 match t.data(h) {
1562 Some(Data::Seq { stride, words }) => words
1563 .iter()
1564 .copied()
1565 .collect::<Vec<_>>()
1566 .chunks(*stride)
1567 .map(<[u64]>::to_vec)
1568 .collect(),
1569 Some(Data::Map(m, _)) => m.values().map(|v| v.to_vec()).collect(),
1570 None => Vec::new(),
1571 }
1572}
1573
1574pub fn keys(h: u64) -> Vec<Key> {
1576 let t = table().lock().unwrap_or_else(|e| e.into_inner());
1577 match t.data(h) {
1578 Some(Data::Map(m, _)) => m.keys().cloned().collect(),
1579 _ => Vec::new(),
1580 }
1581}
1582
1583#[cfg(test)]
1584mod tests {
1585 use super::*;
1586
1587 const Q: Shape = Shape {
1588 elem_words: 1,
1589 assoc: false,
1590 key: KeyKind::Str,
1591 obj: false,
1592 };
1593
1594 #[test]
1595 fn a_queue_pushes_pops_and_changes_handle_on_every_change() {
1596 let h = push(&Q, 0, &[3], false);
1597 let h2 = push(&Q, h, &[4], false);
1598 assert_ne!(h, h2, "each change is a new handle value");
1599 let h3 = push(&Q, h2, &[1], true);
1600 assert_eq!(size(h3), 3);
1601 let mut out = [0];
1602 assert!(get(h3, 2, &mut out));
1603 assert_eq!(out, [4]);
1604 let (h4, ok) = pop(&Q, h3, &mut out, true);
1605 assert!(ok);
1606 assert_eq!(out, [1]);
1607 assert_eq!(size(h4), 2);
1608 }
1609
1610 #[test]
1611 fn clone_deep_copies_inner_collections_and_equal_nest_compares_contents() {
1612 const OUTER: Shape = Shape {
1613 elem_words: 2,
1614 assoc: false,
1615 key: KeyKind::Str,
1616 obj: false,
1617 };
1618 let nest = Nest {
1619 slots: vec![(0, Nest::default())],
1620 };
1621 let inner = push(&Q, push(&Q, 0, &[1], false), &[2], false);
1622 let outer = push(&OUTER, 0, &[inner, 0], false);
1623 let mut minted = Vec::new();
1624 let copy = clone_deep(outer, &nest, &mut minted);
1625 let grown = push(&Q, inner, &[3], false);
1628 let outer = set(&OUTER, outer, 0, &[grown, 0], true);
1629 let mut got = [0, 0];
1630 assert!(get(copy, 0, &mut got));
1631 assert_eq!(size(got[0]), 2, "the copy keeps the old inner contents");
1632 assert!(!equal_nest(outer, copy, &nest), "contents differ");
1633 let again = clone_deep(outer, &nest, &mut minted);
1634 assert!(equal_nest(outer, again, &nest));
1635 minted.iter().for_each(|&h| release(h));
1636 }
1637
1638 fn queue_of(vals: &[u64]) -> u64 {
1639 vals.iter().fold(0, |h, v| push(&Q, h, &[*v], false))
1640 }
1641
1642 fn words(h: u64) -> Vec<u64> {
1643 (0..size(h) as i64)
1644 .map(|i| {
1645 let mut o = [0];
1646 get(h, i, &mut o);
1647 o[0]
1648 })
1649 .collect()
1650 }
1651
1652 #[test]
1653 fn an_element_reference_follows_other_elements_and_writes_through() {
1654 let h = queue_of(&[1, 2, 3]);
1655 let id = ref_open(h, 1);
1656 assert_ne!(id, 0);
1657 let mut out = [0];
1658 assert!(ref_get(id, &mut out));
1659 assert_eq!(out, [2]);
1660 let h = push(&Q, h, &[9], true); let h = insert(&Q, h, 0, &[8]); let h = delete_at(&Q, h, 1); assert!(ref_get(id, &mut out));
1664 assert_eq!(out, [2]);
1665 ref_put(id, &[10]);
1666 assert_eq!(words(h), [8, 1, 10, 3]);
1667 let h = set(&Q, h, 2, &[11], true);
1669 assert!(ref_get(id, &mut out));
1670 assert_eq!(out, [11]);
1671 ref_close(id);
1672 assert!(!ref_get(id, &mut out), "a closed reference is gone");
1673 assert_eq!(words(h), [8, 1, 11, 3]);
1674 }
1675
1676 #[test]
1677 fn a_part_reference_reads_and_writes_only_its_bits() {
1678 let h = queue_of(&[0x0000_0F00_AABB_CCDD, 7]);
1680 let id = ref_open(h, 0);
1681 let mut out = [u64::MAX];
1682 assert!(ref_get_part(id, 8, 8, 32, &mut out));
1683 assert_eq!(out, [0x0FCC]);
1685 ref_put_part(id, 8, 8, 32, &[0x01_55]);
1686 assert_eq!(words(h), [0x0000_0100_AABB_55DD, 7]);
1687 assert!(ref_get_part(id, 0, 32, 0, &mut out));
1689 assert_eq!(out, [0x0000_0100_AABB_55DD]);
1690 ref_close(id);
1691 assert!(!ref_get_part(id, 8, 8, 32, &mut out));
1692 }
1693
1694 #[test]
1695 fn an_outdated_element_reference_drops_its_write_and_keeps_its_id() {
1696 let mut out = [0];
1699 let h = queue_of(&[1, 2, 3]);
1700 let id = ref_open(h, 1);
1701 let h = delete_at(&Q, h, 1);
1702 assert!(!ref_get(id, &mut out));
1703 let other = ref_open(h, 0);
1705 assert_ne!(other, id);
1706 ref_put(id, &[10]);
1707 assert_eq!(words(h), [1, 3]);
1708 ref_close(id);
1709 ref_close(other);
1710
1711 let h = queue_of(&[1, 2, 3]);
1712 let id = ref_open(h, 2);
1713 let (h, _) = pop(&Q, h, &mut out, false);
1714 ref_put(id, &[10]);
1715 assert_eq!(words(h), [1, 2]);
1716 ref_close(id);
1717
1718 let h = queue_of(&[1, 2, 3]);
1719 let id = ref_open(h, 2);
1720 let h = truncate(&Q, h, 2);
1721 ref_put(id, &[10]);
1722 assert_eq!(words(h), [1, 2]);
1723 ref_close(id);
1724
1725 let h = queue_of(&[1, 2, 3]);
1726 let id = ref_open(h, 0);
1727 let h = clear(&Q, h);
1728 let h = push(&Q, h, &[5], false);
1729 ref_put(id, &[10]);
1730 assert_eq!(words(h), [5]);
1731 ref_close(id);
1732
1733 let h = queue_of(&[1, 2, 3]);
1735 let id = ref_open(h, 0);
1736 release(h);
1737 let other = queue_of(&[7, 8, 9]);
1738 ref_put(id, &[10]);
1739 assert_eq!(words(other), [7, 8, 9]);
1740 assert!(!ref_get(id, &mut out));
1741 ref_close(id);
1742 }
1743
1744 #[test]
1745 fn a_reference_outside_the_collection_is_never_open() {
1746 let h = queue_of(&[1]);
1747 assert_eq!(ref_open(h, 1), 0);
1748 assert_eq!(ref_open(h, -1), 0);
1749 assert_eq!(ref_open(0, 0), 0);
1750 ref_put(0, &[5]);
1751 assert_eq!(words(h), [1]);
1752 }
1753
1754 #[test]
1755 fn a_reference_survives_a_frozen_values_first_write() {
1756 let f = frozen_from_words(1, &[1, 2]);
1757 let f = ref_own(&Q, f);
1758 let id = ref_open(f, 1);
1759 let g = insert(&Q, f, 0, &[0]);
1760 ref_put(id, &[5]);
1761 assert_eq!(words(g), [0, 1, 5]);
1762 ref_close(id);
1763 }
1764
1765 #[test]
1766 fn a_clone_is_a_copy_on_write_value() {
1767 let a = push(&Q, 0, &[7], false);
1768 let b = clone(a);
1769 let b2 = set(&Q, b, 0, &[9], true);
1770 let mut out = [0];
1771 get(a, 0, &mut out);
1772 assert_eq!(out, [7], "changing the copy leaves the original");
1773 get(b2, 0, &mut out);
1774 assert_eq!(out, [9]);
1775 }
1776
1777 #[test]
1778 fn a_frozen_value_is_shared_and_never_changed_in_place() {
1779 let f = frozen_from_words(1, &[1, 2]);
1780 assert_eq!(clone(f), f, "a constant needs no copy");
1781 let a = push(&Q, f, &[3], false);
1782 assert_ne!(index(a), index(f), "a change makes a new entry");
1783 assert_eq!(size(f), 2);
1784 assert_eq!(size(a), 3);
1785 release(f);
1786 assert_eq!(size(f), 2, "a constant is never freed");
1787 }
1788
1789 #[test]
1790 fn associative_keys_are_ordered_and_walkable() {
1791 let s = Shape {
1792 elem_words: 1,
1793 assoc: true,
1794 key: KeyKind::Int {
1795 width: 8,
1796 signed: true,
1797 },
1798 obj: false,
1799 };
1800 let mut h = 0;
1801 for k in [5i128, -3, 2] {
1802 h = store(&s, h, Key::Int(k), &[k as u64]);
1803 }
1804 assert_eq!(neighbor(h, None, true), Some(Key::Int(-3)));
1805 assert_eq!(neighbor(h, Some(&Key::Int(2)), true), Some(Key::Int(5)));
1806 assert_eq!(neighbor(h, Some(&Key::Int(5)), true), None);
1807 assert_eq!(key_at(h, 0), Some(Key::Int(-3)));
1808 assert_eq!(key_at(h, 1), Some(Key::Int(2)));
1809 assert_eq!(key_at(h, 2), Some(Key::Int(5)));
1810 assert_eq!(s.key_from_bits(&[0xfd]), Some(Key::Int(-3)));
1811 assert_eq!(s.key_from_bits(&[0x1fd]), None, "an unknown bit");
1812 }
1813
1814 const OQ: Shape = Shape {
1821 elem_words: 2,
1822 assoc: false,
1823 key: KeyKind::Str,
1824 obj: true,
1825 };
1826
1827 fn oa() -> Shape {
1828 Shape {
1829 elem_words: 2,
1830 assoc: true,
1831 key: KeyKind::Int {
1832 width: 8,
1833 signed: true,
1834 },
1835 obj: true,
1836 }
1837 }
1838
1839 fn obj(template: u32) -> u64 {
1841 crate::objects::alloc(crate::netlist::ClassTemplateId(template), 1)
1842 }
1843
1844 fn rc(h: u64) -> Option<u32> {
1845 crate::objects::refcount(h)
1846 }
1847
1848 #[test]
1849 fn a_pushed_object_element_takes_the_callers_reference() {
1850 let a = obj(1013);
1851 let q = push(&OQ, 0, &[a, 0], false);
1852 assert_eq!(rc(a), Some(1), "the queue owns the one reference");
1853 release(q);
1854 assert_eq!(rc(a), None, "releasing the queue frees what it alone held");
1855 }
1856
1857 #[test]
1858 fn overwriting_deleting_and_clearing_release_the_old_element() {
1859 let (a, b, c) = (obj(1014), obj(1014), obj(1014));
1860 crate::objects::retain(a);
1861 crate::objects::retain(b);
1862 crate::objects::retain(c);
1863 let mut q = push(&OQ, 0, &[a, 0], false);
1865 q = push(&OQ, q, &[b, 0], false);
1866 q = push(&OQ, q, &[c, 0], false);
1867 assert_eq!((rc(a), rc(b), rc(c)), (Some(2), Some(2), Some(2)));
1868 crate::objects::retain(b);
1871 q = set(&OQ, q, 0, &[b, 0], true);
1872 assert_eq!(rc(a), Some(1), "an overwritten element is released");
1873 assert_eq!(rc(b), Some(3));
1874 q = delete_at(&OQ, q, 0);
1875 assert_eq!(rc(b), Some(2), "a deleted element is released");
1876 q = clear(&OQ, q);
1877 assert_eq!(rc(b), Some(1));
1878 assert_eq!(rc(c), Some(1), "clear releases every element");
1879 assert_eq!(size(q), 0);
1880 for h in [a, b, c] {
1881 crate::objects::release(h);
1882 assert_eq!(rc(h), None);
1883 }
1884 release(q);
1885 }
1886
1887 #[test]
1888 fn a_pop_hands_its_reference_to_the_caller() {
1889 let a = obj(1015);
1890 let q = push(&OQ, 0, &[a, 0], false);
1891 let mut out = [0, 0];
1892 let (q, ok) = pop(&OQ, q, &mut out, true);
1893 assert!(ok);
1894 assert_eq!(out[0], a);
1895 assert_eq!(rc(a), Some(1), "the reference moved, it was not dropped");
1896 crate::objects::release(out[0]);
1897 assert_eq!(rc(a), None);
1898 release(q);
1899 }
1900
1901 #[test]
1902 fn an_ignored_write_gives_back_the_reference_it_was_handed() {
1903 let (a, b, c) = (obj(1016), obj(1016), obj(1016));
1904 let q = push(&OQ, 0, &[c, 0], false);
1905 let q = set(&OQ, q, 5, &[a, 0], true);
1906 assert_eq!(rc(a), None, "an out-of-range set releases the value");
1907 let q = insert(&OQ, q, -1, &[b, 0]);
1908 assert_eq!(rc(b), None, "an out-of-range insert releases the value");
1909 assert_eq!(rc(c), Some(1), "the element already there is untouched");
1910 release(q);
1911 assert_eq!(rc(c), None);
1912 }
1913
1914 #[test]
1915 fn a_copy_on_write_clone_takes_its_own_reference_per_element() {
1916 let a = obj(1017);
1917 let q = push(&OQ, 0, &[a, 0], false);
1918 let copy = clone(q);
1919 assert_eq!(rc(a), Some(1), "an unchanged clone shares the references");
1920 let b = obj(1017);
1921 let copy = push(&OQ, copy, &[b, 0], false);
1922 assert_eq!(rc(a), Some(2), "unsharing the copy retains each element");
1923 release(q);
1924 assert_eq!(rc(a), Some(1), "the original's holder let go of its own");
1925 release(copy);
1926 assert_eq!(rc(a), None);
1927 assert_eq!(rc(b), None);
1928 }
1929
1930 #[test]
1931 fn resized_append_slice_and_from_copies_retain_what_they_copy() {
1932 let (a, b) = (obj(1018), obj(1018));
1933 let q = push(&OQ, push(&OQ, 0, &[a, 0], false), &[b, 0], false);
1934 assert_eq!((rc(a), rc(b)), (Some(1), Some(1)));
1935 let grown = resized(&OQ, q, 3, &[a, 0]);
1936 assert_eq!((rc(a), rc(b)), (Some(3), Some(2)));
1939 let sl = slice(&OQ, q, 1, 1);
1940 assert_eq!(rc(b), Some(3));
1941 let ap = append(&OQ, 0, q);
1942 assert_eq!((rc(a), rc(b)), (Some(4), Some(4)));
1943 let fc = from_copies(&OQ, &[a, 0, b, 0]);
1944 assert_eq!((rc(a), rc(b)), (Some(5), Some(5)));
1945 for h in [q, grown, sl, ap, fc] {
1946 release(h);
1947 }
1948 assert_eq!(
1949 (rc(a), rc(b)),
1950 (None, None),
1951 "no holder left, nothing leaks"
1952 );
1953 }
1954
1955 #[test]
1956 fn an_associative_array_owns_values_and_its_default() {
1957 let (a, b, d) = (obj(1019), obj(1019), obj(1019));
1958 let s = oa();
1959 let mut h = store(&s, 0, Key::Int(1), &[a, 0]);
1960 crate::objects::retain(a);
1961 h = store(&s, h, Key::Int(2), &[a, 0]);
1962 assert_eq!(rc(a), Some(2), "two keys, two references");
1963 h = store(&s, h, Key::Int(1), &[b, 0]);
1964 assert_eq!(rc(a), Some(1), "replacing a value releases the old one");
1965 h = delete_key(&s, h, &Key::Int(2));
1966 assert_eq!(rc(a), None, "deleting a key releases its value");
1967 h = delete_key(&s, h, &Key::Int(99));
1968 assert_eq!(rc(b), Some(1), "deleting an absent key changes nothing");
1969 h = set_default(&s, h, &[d, 0]);
1970 assert_eq!(rc(d), Some(1));
1971 h = clear(&s, h);
1972 assert_eq!(rc(b), None);
1973 assert_eq!(rc(d), Some(1), "clear keeps the default's reference");
1974 release(h);
1975 assert_eq!(rc(d), None, "freeing the array frees its default");
1976 }
1977
1978 #[test]
1982 fn a_handle_keyed_map_owns_its_keys() {
1983 let (k1, k2) = (obj(1021), obj(1021));
1984 let s = Shape {
1985 elem_words: 1,
1986 assoc: true,
1987 key: KeyKind::Obj,
1988 obj: false,
1989 };
1990 let key = |k: u64| Key::Int(i128::from(k));
1991 let mut h = store(&s, 0, key(k1), &[1]);
1992 assert_eq!(rc(k1), Some(2), "a new key takes its own reference");
1993 h = store(&s, h, key(k1), &[2]);
1994 assert_eq!(rc(k1), Some(2), "re-storing an existing key adds none");
1995 h = store(&s, h, key(k2), &[3]);
1996 let c = clone(h);
1997 let c = store(&s, c, key(k2), &[4]);
1998 assert_eq!(rc(k1), Some(3), "an unshared copy retains each key");
1999 h = delete_key(&s, h, &key(k1));
2000 assert_eq!(rc(k1), Some(2), "deleting a key releases it");
2001 h = clear(&s, h);
2002 assert_eq!(rc(k2), Some(2), "clear releases every key");
2003 release(h);
2004 release(c);
2005 assert_eq!(rc(k1), Some(1), "freeing the copy releases its keys");
2006 assert_eq!(rc(k2), Some(1));
2007 crate::objects::release(k1);
2008 crate::objects::release(k2);
2009 }
2010
2011 #[test]
2012 fn a_permutation_moves_references_without_changing_counts() {
2013 let (a, b) = (obj(1020), obj(1020));
2014 let q = push(&OQ, push(&OQ, 0, &[a, 0], false), &[b, 0], false);
2015 let q = permute(&OQ, q, &[1, 0]);
2016 let mut out = [0, 0];
2017 assert!(get(q, 0, &mut out));
2018 assert_eq!(out[0], b);
2019 assert_eq!((rc(a), rc(b)), (Some(1), Some(1)));
2020 release(q);
2021 assert_eq!((rc(a), rc(b)), (None, None));
2022 }
2023
2024 #[test]
2030 fn frozen_snapshot_refuses_a_live_collection() {
2031 let live = from_words(&Q, &[1, 2]);
2032 let why = frozen_snapshot().expect_err("a live collection cannot be frozen into an image");
2033 assert!(why.contains("not a constant"), "{why}");
2034 release(live);
2035 }
2036}