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 nested: Nested,
75 key_objs: bool,
76}
77
78pub const MAX_NESTED_OBJS: usize = 8;
83
84#[derive(Clone, Copy, Debug, PartialEq, Eq)]
89pub struct Nested {
90 pub n: u8,
91 pub at: [u32; MAX_NESTED_OBJS],
92}
93
94impl Nested {
95 pub const NONE: Nested = Nested {
97 n: 0,
98 at: [0; MAX_NESTED_OBJS],
99 };
100
101 fn slots(&self) -> &[u32] {
102 &self.at[..usize::from(self.n)]
103 }
104}
105
106fn elem_handles(objs: bool, nested: &Nested, elem: &[u64], mut f: impl FnMut(u64)) {
109 if objs && let Some(&w) = elem.first() {
110 f(w);
111 }
112 for &off in nested.slots() {
113 let h = bits64(elem, off as usize);
114 if h != 0 {
115 f(h);
116 }
117 }
118}
119
120impl Held {
121 fn each_handle(&self, with_default: bool, mut f: impl FnMut(u64)) {
124 if !self.objs && self.nested.n == 0 {
125 return;
126 }
127 let (objs, nested) = (self.objs, self.nested);
128 match &self.data {
129 Data::Seq { stride, words } if nested.n == 0 => {
130 words.iter().step_by((*stride).max(1)).for_each(|&w| f(w))
131 }
132 Data::Seq { stride, words } => {
133 let stride = (*stride).max(1);
134 let mut buf = Vec::with_capacity(stride);
135 let mut it = words.iter().copied();
136 loop {
137 buf.clear();
138 buf.extend(it.by_ref().take(stride));
139 if buf.len() < stride {
140 break;
141 }
142 elem_handles(objs, &nested, &buf, &mut f);
143 }
144 }
145 Data::Map(m, dflt) => {
146 for v in m.values().chain(dflt.iter().filter(|_| with_default)) {
147 elem_handles(objs, &nested, v, &mut f);
148 }
149 }
150 }
151 }
152
153 fn each_key(&self, mut f: impl FnMut(u64)) {
155 if !self.key_objs {
156 return;
157 }
158 if let Data::Map(m, _) = &self.data {
159 for k in m.keys() {
160 if let Key::Int(v) = k {
161 f(*v as u64);
162 }
163 }
164 }
165 }
166
167 fn release_elements(&self) {
170 self.each_handle(false, crate::objects::release);
171 }
172}
173
174impl Clone for Held {
175 fn clone(&self) -> Held {
176 self.each_handle(true, crate::objects::retain);
177 self.each_key(crate::objects::retain);
178 Held {
179 data: self.data.clone(),
180 objs: self.objs,
181 nested: self.nested,
182 key_objs: self.key_objs,
183 }
184 }
185}
186
187impl Drop for Held {
188 fn drop(&mut self) {
189 self.each_handle(true, crate::objects::release);
190 self.each_key(crate::objects::release);
191 }
192}
193
194struct Entry {
195 version: u32,
196 data: Arc<Held>,
197 cursor: Option<(usize, Key)>,
199 frozen: bool,
203}
204
205#[derive(Default)]
206struct Table {
207 entries: Vec<Option<Entry>>,
209 versions: Vec<u32>,
211 free: Vec<u32>,
212 refs: Vec<Option<ElemRef>>,
216 free_refs: Vec<u32>,
217 n_refs: usize,
218}
219
220#[derive(Clone)]
226struct ElemRef {
227 entry: usize,
228 index: i64,
229 key: Option<Key>,
233 live: bool,
234}
235
236fn table() -> &'static Mutex<Table> {
237 static T: OnceLock<Mutex<Table>> = OnceLock::new();
238 T.get_or_init(|| {
239 Mutex::new(Table {
240 entries: vec![None],
241 versions: vec![0],
242 free: Vec::new(),
243 refs: Vec::new(),
244 free_refs: Vec::new(),
245 n_refs: 0,
246 })
247 })
248}
249
250fn index(h: u64) -> usize {
251 (h & 0xffff_ffff) as usize
252}
253
254impl Table {
255 fn held(&self, h: u64) -> Option<&Held> {
256 self.entries.get(index(h))?.as_ref().map(|e| &*e.data)
257 }
258
259 fn data(&self, h: u64) -> Option<&Data> {
260 self.held(h).map(|e| &e.data)
261 }
262
263 fn alloc(&mut self, data: Held) -> u64 {
264 let i = match self.free.pop() {
265 Some(i) => i as usize,
266 None => {
267 self.entries.push(None);
268 self.versions.push(0);
269 self.entries.len() - 1
270 }
271 };
272 let version = self.versions[i].wrapping_add(1);
273 self.versions[i] = version;
274 self.entries[i] = Some(Entry {
275 version,
276 data: Arc::new(data),
277 cursor: None,
278 frozen: false,
279 });
280 (u64::from(version) << 32) | i as u64
281 }
282
283 fn release(&mut self, h: u64) {
287 let i = index(h);
288 if i != 0
289 && self.entries.get(i).is_some_and(|e| {
290 e.as_ref()
291 .is_some_and(|e| !e.frozen && u64::from(e.version) == h >> 32)
292 })
293 {
294 self.refs_outdated(i, 0);
295 self.entries[i] = None;
296 self.free.push(i as u32);
297 }
298 }
299
300 fn refs_outdated(&mut self, entry: usize, from: i64) {
303 if self.n_refs == 0 {
304 return;
305 }
306 for r in self.refs.iter_mut().flatten() {
307 if r.live && r.entry == entry && r.index >= from {
308 r.live = false;
309 }
310 }
311 }
312
313 fn refs_key_removed(&mut self, entry: usize, key: &Key) {
317 if self.n_refs == 0 {
318 return;
319 }
320 for r in self.refs.iter_mut().flatten() {
321 if r.live && r.entry == entry && r.key.as_ref() == Some(key) {
322 r.live = false;
323 }
324 }
325 }
326
327 fn refs_removed(&mut self, entry: usize, i: i64) {
330 if self.n_refs == 0 {
331 return;
332 }
333 for rr in self.refs.iter_mut().flatten() {
334 if !rr.live || rr.entry != entry || rr.index < i {
335 continue;
336 }
337 if rr.index == i {
338 rr.live = false;
339 } else {
340 rr.index -= 1;
341 }
342 }
343 }
344
345 fn refs_inserted(&mut self, entry: usize, i: i64) {
348 if self.n_refs == 0 {
349 return;
350 }
351 for r in self.refs.iter_mut().flatten() {
352 if r.live && r.entry == entry && r.index >= i {
353 r.index += 1;
354 }
355 }
356 }
357
358 fn refs_moved(&mut self, from: usize, to: usize) {
361 if self.n_refs == 0 {
362 return;
363 }
364 for r in self.refs.iter_mut().flatten() {
365 if r.live && r.entry == from {
366 r.entry = to;
367 }
368 }
369 }
370
371 fn modify(&mut self, h: u64, empty: impl FnOnce() -> Held, f: impl FnOnce(&mut Held)) -> u64 {
374 let i = index(h);
375 match self.entries.get_mut(i).and_then(|e| e.as_mut()) {
376 Some(e) if e.frozen => {
377 let mut d = (*e.data).clone();
378 f(&mut d);
379 let new = self.alloc(d);
380 self.refs_moved(i, index(new));
381 new
382 }
383 Some(e) if i != 0 => {
384 f(Arc::make_mut(&mut e.data));
385 e.version = e.version.wrapping_add(1);
386 e.cursor = None;
387 self.versions[i] = e.version;
388 (u64::from(e.version) << 32) | i as u64
389 }
390 _ => {
391 let mut d = empty();
392 f(&mut d);
393 self.alloc(d)
394 }
395 }
396 }
397}
398
399#[derive(Clone, Copy, Debug)]
402pub struct Shape {
403 pub elem_words: usize,
404 pub assoc: bool,
405 pub key: KeyKind,
406 pub obj: bool,
409 pub nested: Nested,
413}
414
415#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
417pub enum KeyKind {
418 Int {
420 width: u32,
421 signed: bool,
422 },
423 Str,
424 Obj,
427}
428
429impl Shape {
430 fn empty(&self) -> Held {
431 self.held(if self.assoc {
432 Data::Map(BTreeMap::new(), None)
433 } else {
434 Data::Seq {
435 stride: self.elem_words.max(1),
436 words: VecDeque::new(),
437 }
438 })
439 }
440
441 fn held(&self, data: Data) -> Held {
442 Held {
443 data,
444 objs: self.obj,
445 nested: self.nested,
446 key_objs: self.key == KeyKind::Obj,
447 }
448 }
449
450 pub fn discard(&self, val: &[u64]) {
454 elem_handles(self.obj, &self.nested, val, crate::objects::release);
455 }
456
457 pub fn key_from_bits(&self, bits: &[u64]) -> Option<Key> {
460 match self.key {
461 KeyKind::Str => Some(Key::Str(crate::strings::bytes(bits[0]).to_vec())),
462 KeyKind::Int { .. } | KeyKind::Obj => {
463 let (width, signed) = if let KeyKind::Int { width, signed } = self.key {
464 (width, signed)
465 } else {
466 (64, false)
468 };
469 let w = width as usize;
470 let bit = |i: usize| (bits.get(i / 64).copied().unwrap_or(0) >> (i % 64)) & 1;
471 if (w..2 * w).any(|i| bit(i) != 0) {
472 return None;
473 }
474 if w <= 127 {
475 let mut v: i128 = 0;
476 for i in 0..w {
477 v |= (bit(i) as i128) << i;
478 }
479 if signed && w > 0 && bit(w - 1) == 1 {
480 v -= 1i128 << w;
481 }
482 Some(Key::Int(v))
483 } else {
484 let n = w.div_ceil(64);
485 let mut words = vec![0u64; n];
486 for i in 0..w {
487 words[i / 64] |= bit(i) << (i % 64);
488 }
489 words.reverse();
490 Some(Key::Big(words))
491 }
492 }
493 }
494 }
495
496 pub fn key_to_bits(&self, key: &Key, out: &mut [u64]) {
498 out.fill(0);
499 match key {
500 Key::Str(s) => out[0] = crate::strings::intern(s),
501 Key::Int(v) => {
502 let width = match self.key {
503 KeyKind::Int { width, .. } => width,
504 KeyKind::Obj => 64,
505 KeyKind::Str => return,
506 };
507 for i in 0..width as usize {
508 if (v >> i.min(127)) & 1 == 1 {
509 out[i / 64] |= 1 << (i % 64);
510 }
511 }
512 }
513 Key::Big(words) => {
514 for (i, w) in words.iter().rev().enumerate() {
515 if let Some(o) = out.get_mut(i) {
516 *o = *w;
517 }
518 }
519 }
520 }
521 }
522}
523
524pub fn size(h: u64) -> usize {
526 let t = table().lock().unwrap_or_else(|e| e.into_inner());
527 t.data(h).map_or(0, |d| d.len())
528}
529
530pub fn get(h: u64, i: i64, out: &mut [u64]) -> bool {
533 let t = table().lock().unwrap_or_else(|e| e.into_inner());
534 let Some(Data::Seq { stride, words }) = t.data(h) else {
535 return false;
536 };
537 let n = words.len() / stride;
538 if i < 0 || i as usize >= n {
539 return false;
540 }
541 let base = i as usize * stride;
542 for (k, o) in out.iter_mut().enumerate().take(*stride) {
543 *o = words[base + k];
544 }
545 true
546}
547
548pub fn lookup(h: u64, key: &Key, out: &mut [u64]) -> bool {
551 let t = table().lock().unwrap_or_else(|e| e.into_inner());
552 let Some(Data::Map(m, dflt)) = t.data(h) else {
553 return false;
554 };
555 match m.get(key).or(dflt.as_ref()) {
556 Some(v) => {
557 let n = out.len().min(v.len());
558 out[..n].copy_from_slice(&v[..n]);
559 true
560 }
561 None => false,
562 }
563}
564
565pub fn exists(h: u64, key: &Key) -> bool {
567 let t = table().lock().unwrap_or_else(|e| e.into_inner());
568 matches!(t.data(h), Some(Data::Map(m, _)) if m.contains_key(key))
569}
570
571pub fn set(shape: &Shape, h: u64, i: i64, val: &[u64], queue: bool) -> u64 {
578 let n = size(h) as i64;
579 if i < 0 || i > n || (i == n && !queue) {
580 shape.discard(val);
581 return h;
582 }
583 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
584 t.modify(
585 h,
586 || shape.empty(),
587 |d| {
588 let Held {
589 data, objs, nested, ..
590 } = d;
591 if let Data::Seq { stride, words } = data {
592 let base = i as usize * *stride;
593 if base == words.len() {
594 words.extend(val.iter().copied().take(*stride));
595 words.resize(base + *stride, 0);
596 } else {
597 if *objs || nested.n > 0 {
598 let old: Vec<u64> = words.range(base..base + *stride).copied().collect();
599 elem_handles(*objs, nested, &old, crate::objects::release);
600 }
601 for k in 0..*stride {
602 words[base + k] = val.get(k).copied().unwrap_or(0);
603 }
604 }
605 }
606 },
607 )
608}
609
610pub fn store(shape: &Shape, h: u64, key: Key, val: &[u64]) -> u64 {
613 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
614 let v: Box<[u64]> = val[..shape.elem_words.min(val.len())].into();
615 t.modify(
616 h,
617 || shape.empty(),
618 |d| {
619 let Held {
620 data,
621 objs,
622 nested,
623 key_objs,
624 } = d;
625 if let Data::Map(m, _) = data {
626 if *key_objs
628 && !m.contains_key(&key)
629 && let Key::Int(k) = &key
630 {
631 crate::objects::retain(*k as u64);
632 }
633 if let Some(old) = m.insert(key, v) {
634 elem_handles(*objs, nested, &old, crate::objects::release);
635 }
636 }
637 },
638 )
639}
640
641pub fn insert(shape: &Shape, h: u64, i: i64, val: &[u64]) -> u64 {
645 let n = size(h) as i64;
646 if i < 0 || i > n {
647 shape.discard(val);
648 return h;
649 }
650 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
651 let new = t.modify(
652 h,
653 || shape.empty(),
654 |d| {
655 if let Data::Seq { stride, words } = &mut d.data {
656 let at = i as usize * *stride;
657 for k in (0..*stride).rev() {
658 words.insert(at, val.get(k).copied().unwrap_or(0));
659 }
660 }
661 },
662 );
663 t.refs_inserted(index(new), i);
664 new
665}
666
667pub fn push(shape: &Shape, h: u64, val: &[u64], front: bool) -> u64 {
669 if front {
670 insert(shape, h, 0, val)
671 } else {
672 insert(shape, h, size(h) as i64, val)
673 }
674}
675
676pub fn pop(shape: &Shape, h: u64, out: &mut [u64], front: bool) -> (u64, bool) {
680 let n = size(h);
681 if n == 0 {
682 return (h, false);
683 }
684 let i = if front { 0 } else { n - 1 };
685 get(h, i as i64, out);
686 (remove_at(shape, h, i as i64, false), true)
687}
688
689pub fn truncate(shape: &Shape, h: u64, keep: usize) -> u64 {
693 if size(h) <= keep {
694 return h;
695 }
696 eprintln!(
697 "Warning: bounded queue exceeded its bound; elements beyond index {} discarded",
698 keep - 1
699 );
700 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
701 let new = t.modify(
702 h,
703 || shape.empty(),
704 |d| {
705 let Held {
706 data, objs, nested, ..
707 } = d;
708 if let Data::Seq { stride, words } = data {
709 let at = keep * *stride;
710 if *objs || nested.n > 0 {
711 let tail: Vec<u64> = words.iter().skip(at).copied().collect();
712 for elem in tail.chunks((*stride).max(1)) {
713 elem_handles(*objs, nested, elem, crate::objects::release);
714 }
715 }
716 words.truncate(at);
717 }
718 },
719 );
720 t.refs_outdated(index(new), keep as i64);
721 new
722}
723
724pub fn delete_at(shape: &Shape, h: u64, i: i64) -> u64 {
727 remove_at(shape, h, i, true)
728}
729
730fn remove_at(shape: &Shape, h: u64, i: i64, release: bool) -> u64 {
733 let n = size(h) as i64;
734 if i < 0 || i >= n {
735 return h;
736 }
737 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
738 let new = t.modify(
739 h,
740 || shape.empty(),
741 |d| {
742 let Held {
743 data, objs, nested, ..
744 } = d;
745 if let Data::Seq { stride, words } = data {
746 let at = i as usize * *stride;
747 if release && (*objs || nested.n > 0) {
748 let old: Vec<u64> = words.range(at..at + *stride).copied().collect();
749 elem_handles(*objs, nested, &old, crate::objects::release);
750 }
751 words.drain(at..at + *stride);
752 }
753 },
754 );
755 t.refs_removed(index(new), i);
756 new
757}
758
759pub fn delete_key(shape: &Shape, h: u64, key: &Key) -> u64 {
761 if !exists(h, key) {
762 return h;
763 }
764 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
765 let new = t.modify(
766 h,
767 || shape.empty(),
768 |d| {
769 let Held {
770 data,
771 objs,
772 nested,
773 key_objs,
774 } = d;
775 if let Data::Map(m, _) = data
776 && let Some(old) = m.remove(key)
777 {
778 if *key_objs && let Key::Int(k) = key {
779 crate::objects::release(*k as u64);
780 }
781 elem_handles(*objs, nested, &old, crate::objects::release);
782 }
783 },
784 );
785 t.refs_key_removed(index(new), key);
786 new
787}
788
789pub fn set_default(shape: &Shape, h: u64, val: &[u64]) -> u64 {
793 let v: Box<[u64]> = val[..shape.elem_words.min(val.len())].into();
794 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
795 t.modify(
796 h,
797 || shape.empty(),
798 |d| {
799 let Held {
800 data, objs, nested, ..
801 } = d;
802 if let Data::Map(_, dflt) = data
803 && let Some(old) = dflt.replace(v)
804 {
805 elem_handles(*objs, nested, &old, crate::objects::release);
806 }
807 },
808 )
809}
810
811pub fn clear(shape: &Shape, h: u64) -> u64 {
813 if h == 0 {
814 return 0;
815 }
816 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
817 let new = t.modify(
818 h,
819 || shape.empty(),
820 |d| {
821 d.release_elements();
822 d.each_key(crate::objects::release);
823 match &mut d.data {
824 Data::Map(m, _) => m.clear(),
825 Data::Seq { words, .. } => words.clear(),
826 }
827 },
828 );
829 t.refs_outdated(index(new), 0);
830 new
831}
832
833pub fn clone(h: u64) -> u64 {
837 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
838 if t.entries
839 .get(index(h))
840 .and_then(|e| e.as_ref())
841 .is_some_and(|e| e.frozen)
842 {
843 return h;
844 }
845 match t.entries.get(index(h)).and_then(|e| e.as_ref()) {
846 Some(e) => {
847 let data = Arc::clone(&e.data);
848 let fresh = t.alloc(Held {
849 data: Data::Map(BTreeMap::new(), None),
850 objs: false,
851 nested: Nested::NONE,
852 key_objs: false,
853 });
854 if let Some(e) = t.entries[index(fresh)].as_mut() {
855 e.data = data;
856 }
857 fresh
858 }
859 None => 0,
860 }
861}
862
863#[derive(Clone, Debug, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
868pub struct Nest {
869 pub slots: Vec<(u32, Nest)>,
870}
871
872fn bits64(words: &[u64], at: usize) -> u64 {
874 let (w, s) = (at / 64, at % 64);
875 let lo = words.get(w).copied().unwrap_or(0) >> s;
876 if s == 0 {
877 lo
878 } else {
879 lo | (words.get(w + 1).copied().unwrap_or(0) << (64 - s))
880 }
881}
882
883fn set_bits64(words: &mut [u64], at: usize, v: u64) {
884 let (w, s) = (at / 64, at % 64);
885 if s == 0 {
886 if let Some(x) = words.get_mut(w) {
887 *x = v;
888 }
889 return;
890 }
891 if let Some(x) = words.get_mut(w) {
892 *x = (*x & (u64::MAX >> (64 - s))) | (v << s);
893 }
894 if let Some(x) = words.get_mut(w + 1) {
895 *x = (*x & (u64::MAX << s)) | (v >> (64 - s));
896 }
897}
898
899fn elem_list(h: u64) -> Vec<(Option<Key>, Vec<u64>)> {
902 let t = table().lock().unwrap_or_else(|e| e.into_inner());
903 match t.data(h) {
904 None => Vec::new(),
905 Some(Data::Seq { stride, words }) => words
906 .iter()
907 .copied()
908 .collect::<Vec<_>>()
909 .chunks((*stride).max(1))
910 .map(|c| (None, c.to_vec()))
911 .collect(),
912 Some(Data::Map(m, _)) => m
913 .iter()
914 .map(|(k, v)| (Some(k.clone()), v.to_vec()))
915 .collect(),
916 }
917}
918
919pub fn clone_deep(h: u64, nest: &Nest, minted: &mut Vec<u64>) -> u64 {
925 let fresh = clone(h);
926 if fresh != 0 {
927 minted.push(fresh);
928 }
929 if fresh == 0 || nest.slots.is_empty() {
930 return fresh;
931 }
932 let mut inner: Vec<(usize, u64)> = Vec::new();
933 {
934 let t = table().lock().unwrap_or_else(|e| e.into_inner());
935 let Some(e) = t.entries.get(index(fresh)).and_then(|e| e.as_ref()) else {
936 return fresh;
937 };
938 if e.frozen {
939 return fresh;
940 }
941 let mut visit = |el: &[u64]| {
942 for (k, (off, _)) in nest.slots.iter().enumerate() {
943 let x = bits64(el, *off as usize);
944 if x != 0 {
945 inner.push((k, x));
946 }
947 }
948 };
949 match &e.data.data {
950 Data::Seq { stride, words } => words
951 .iter()
952 .copied()
953 .collect::<Vec<_>>()
954 .chunks((*stride).max(1))
955 .for_each(&mut visit),
956 Data::Map(m, d) => m.values().chain(d.iter()).for_each(|v| visit(v)),
957 }
958 }
959 let mut copies: std::collections::HashMap<(usize, u64), u64> = std::collections::HashMap::new();
960 for (k, x) in inner {
961 copies
962 .entry((k, x))
963 .or_insert_with(|| clone_deep(x, &nest.slots[k].1, minted));
964 }
965 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
966 let Some(e) = t.entries.get_mut(index(fresh)).and_then(|e| e.as_mut()) else {
967 return fresh;
968 };
969 let held = Arc::make_mut(&mut e.data);
970 let mut rewrite = |el: &mut [u64]| {
971 for (k, (off, _)) in nest.slots.iter().enumerate() {
972 let x = bits64(el, *off as usize);
973 if let Some(&n) = copies.get(&(k, x)) {
974 set_bits64(el, *off as usize, n);
975 }
976 }
977 };
978 match &mut held.data {
979 Data::Seq { stride, words } => words
980 .make_contiguous()
981 .chunks_mut((*stride).max(1))
982 .for_each(&mut rewrite),
983 Data::Map(m, d) => m
984 .values_mut()
985 .map(|v| &mut v[..])
986 .chain(d.iter_mut().map(|v| &mut v[..]))
987 .for_each(rewrite),
988 }
989 fresh
990}
991
992pub fn equal_nest(a: u64, b: u64, nest: &Nest) -> bool {
996 if nest.slots.is_empty() {
997 return equal(a, b);
998 }
999 let (x, y) = (elem_list(a), elem_list(b));
1000 x.len() == y.len()
1001 && x.iter().zip(&y).all(|((ka, ea), (kb, eb))| {
1002 if ka != kb || ea.len() != eb.len() {
1003 return false;
1004 }
1005 let (mut ea, mut eb) = (ea.clone(), eb.clone());
1006 let mut same = true;
1007 for (off, sub) in &nest.slots {
1008 let at = *off as usize;
1009 same &= equal_nest(bits64(&ea, at), bits64(&eb, at), sub);
1010 set_bits64(&mut ea, at, 0);
1011 set_bits64(&mut eb, at, 0);
1012 }
1013 same && ea == eb
1014 })
1015}
1016
1017pub fn live_count() -> usize {
1020 let t = table().lock().unwrap_or_else(|e| e.into_inner());
1021 t.entries.iter().filter(|e| e.is_some()).count()
1022}
1023
1024pub fn release(h: u64) {
1026 table().lock().unwrap_or_else(|e| e.into_inner()).release(h);
1027}
1028
1029pub fn ref_open(h: u64, i: i64) -> u64 {
1037 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
1038 let e = index(h);
1039 let n = t.data(h).filter(|_| e != 0).map_or(0, |d| d.len() as i64);
1040 if i < 0 || i >= n {
1041 return 0;
1042 }
1043 t.ref_push(ElemRef {
1044 entry: e,
1045 index: i,
1046 key: None,
1047 live: true,
1048 })
1049}
1050
1051pub fn ref_open_key(h: u64, key: Key) -> u64 {
1058 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
1059 let e = index(h);
1060 if e == 0 || !matches!(t.data(h), Some(Data::Map(..))) {
1061 return 0;
1062 }
1063 t.ref_push(ElemRef {
1064 entry: e,
1065 index: 0,
1066 key: Some(key),
1067 live: true,
1068 })
1069}
1070
1071impl Table {
1072 fn ref_push(&mut self, rec: ElemRef) -> u64 {
1073 let rec = Some(rec);
1074 self.n_refs += 1;
1075 match self.free_refs.pop() {
1076 Some(k) => {
1077 self.refs[k as usize] = rec;
1078 u64::from(k) + 1
1079 }
1080 None => {
1081 self.refs.push(rec);
1082 self.refs.len() as u64
1083 }
1084 }
1085 }
1086}
1087
1088pub fn ref_own(shape: &Shape, h: u64) -> u64 {
1092 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
1093 if h == 0 {
1094 return if shape.assoc {
1096 t.modify(h, || shape.empty(), |_| {})
1097 } else {
1098 0
1099 };
1100 }
1101 if t.entries
1102 .get(index(h))
1103 .and_then(|e| e.as_ref())
1104 .is_some_and(|e| e.frozen)
1105 {
1106 t.modify(h, || shape.empty(), |_| {})
1107 } else {
1108 h
1109 }
1110}
1111
1112fn ref_rec(t: &Table, id: u64) -> Option<ElemRef> {
1113 t.refs.get(id.wrapping_sub(1) as usize).cloned().flatten()
1114}
1115
1116pub fn ref_get(id: u64, out: &mut [u64]) -> bool {
1120 let t = table().lock().unwrap_or_else(|e| e.into_inner());
1121 let Some(r) = ref_rec(&t, id).filter(|r| r.live) else {
1122 return false;
1123 };
1124 match (&r.key, t.data(r.entry as u64)) {
1125 (Some(key), Some(Data::Map(m, dflt))) => match m.get(key).or(dflt.as_ref()) {
1126 Some(v) => {
1127 let n = out.len().min(v.len());
1128 out[..n].copy_from_slice(&v[..n]);
1129 true
1130 }
1131 None => false,
1132 },
1133 (None, _) => {
1134 drop(t);
1135 get(r.entry as u64, r.index, out)
1136 }
1137 _ => false,
1138 }
1139}
1140
1141pub fn ref_put(id: u64, val: &[u64]) {
1146 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
1147 let Some(r) = ref_rec(&t, id).filter(|r| r.live) else {
1148 return;
1149 };
1150 let Some(e) = t.entries.get_mut(r.entry).and_then(|e| e.as_mut()) else {
1151 return;
1152 };
1153 let held = Arc::make_mut(&mut e.data);
1154 let key_objs = held.key_objs;
1155 match (&mut held.data, r.key) {
1156 (Data::Seq { stride, words }, None) => {
1157 let base = r.index as usize * *stride;
1158 if base + *stride <= words.len() {
1159 for k in 0..*stride {
1160 words[base + k] = val.get(k).copied().unwrap_or(0);
1161 }
1162 e.cursor = None;
1163 }
1164 }
1165 (Data::Map(m, _), Some(key)) => {
1166 match m.get_mut(&key) {
1167 Some(slot) => {
1168 let n = slot.len().min(val.len());
1169 slot[..n].copy_from_slice(&val[..n]);
1170 }
1171 None => {
1172 if key_objs && let Key::Int(k) = &key {
1173 crate::objects::retain(*k as u64);
1174 }
1175 m.insert(key, val.into());
1176 }
1177 }
1178 e.cursor = None;
1179 }
1180 _ => {}
1181 }
1182}
1183
1184fn bit_at(w: &[u64], i: usize) -> bool {
1185 w.get(i / 64).is_some_and(|x| (x >> (i % 64)) & 1 != 0)
1186}
1187
1188fn set_bit(w: &mut [u64], i: usize, v: bool) {
1189 if let Some(x) = w.get_mut(i / 64) {
1190 let m = 1u64 << (i % 64);
1191 *x = if v { *x | m } else { *x & !m };
1192 }
1193}
1194
1195pub fn ref_get_part(id: u64, lo: u64, w: u32, big_w: u32, out: &mut [u64]) -> bool {
1202 if crate::winref::is_window(id) {
1203 return crate::winref::get_part(id, lo, w, big_w, out);
1204 }
1205 if big_w == 0 {
1206 return ref_get(id, out);
1207 }
1208 let mut elem = vec![0u64; (2 * big_w as usize).div_ceil(64)];
1209 if !ref_get(id, &mut elem) {
1210 return false;
1211 }
1212 out.fill(0);
1213 for k in 0..w as usize {
1214 let i = lo as usize + k;
1217 if i < big_w as usize {
1218 set_bit(out, k, bit_at(&elem, i));
1219 set_bit(out, w as usize + k, bit_at(&elem, big_w as usize + i));
1220 }
1221 }
1222 true
1223}
1224
1225pub fn ref_put_part(id: u64, lo: u64, w: u32, big_w: u32, val: &[u64]) {
1231 if crate::winref::is_window(id) {
1232 return crate::winref::put_part(id, lo, w, big_w, val);
1233 }
1234 if big_w == 0 {
1235 return ref_put(id, val);
1236 }
1237 let mut elem = vec![0u64; (2 * big_w as usize).div_ceil(64)];
1238 if !ref_get(id, &mut elem) {
1239 return;
1240 }
1241 for k in 0..w as usize {
1242 let i = lo as usize + k;
1243 if i < big_w as usize {
1244 set_bit(&mut elem, i, bit_at(val, k));
1245 set_bit(&mut elem, big_w as usize + i, bit_at(val, w as usize + k));
1246 }
1247 }
1248 ref_put(id, &elem);
1249}
1250
1251pub fn ref_close(id: u64) {
1253 if crate::winref::is_window(id) {
1254 return crate::winref::close(id);
1255 }
1256 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
1257 let k = id.wrapping_sub(1) as usize;
1258 if t.refs.get_mut(k).and_then(Option::take).is_some() {
1259 t.free_refs.push(k as u32);
1260 t.n_refs -= 1;
1261 }
1262}
1263
1264#[cfg(test)]
1270pub(crate) fn is_live(h: u64) -> bool {
1271 let t = table().lock().unwrap_or_else(|e| e.into_inner());
1272 t.entries
1273 .get(index(h))
1274 .and_then(|e| e.as_ref())
1275 .is_some_and(|e| u64::from(e.version) == h >> 32)
1276}
1277
1278pub fn resized(shape: &Shape, src: u64, n: usize, dflt: &[u64]) -> u64 {
1282 let stride = shape.elem_words.max(1);
1283 let mut words = VecDeque::with_capacity(n * stride);
1284 {
1285 let t = table().lock().unwrap_or_else(|e| e.into_inner());
1286 if let Some(Data::Seq { words: w, .. }) = t.data(src) {
1287 words.extend(w.iter().copied().take(n * stride));
1288 }
1289 }
1290 while words.len() < n * stride {
1291 for k in 0..stride {
1292 words.push_back(dflt.get(k).copied().unwrap_or(0));
1293 }
1294 }
1295 retain_elems(shape, words.iter().copied());
1296 table()
1297 .lock()
1298 .unwrap_or_else(|e| e.into_inner())
1299 .alloc(shape.held(Data::Seq { stride, words }))
1300}
1301
1302fn retain_elems(shape: &Shape, words: impl Iterator<Item = u64>) {
1305 if shape.nested.n == 0 {
1306 if shape.obj {
1307 words
1308 .step_by(shape.elem_words.max(1))
1309 .for_each(crate::objects::retain);
1310 }
1311 return;
1312 }
1313 let stride = shape.elem_words.max(1);
1314 let mut words = words;
1315 let mut buf = Vec::with_capacity(stride);
1316 loop {
1317 buf.clear();
1318 buf.extend(words.by_ref().take(stride));
1319 if buf.len() < stride {
1320 break;
1321 }
1322 elem_handles(shape.obj, &shape.nested, &buf, crate::objects::retain);
1323 }
1324}
1325
1326pub fn from_words(shape: &Shape, elems: &[u64]) -> u64 {
1329 let stride = shape.elem_words.max(1);
1330 table()
1331 .lock()
1332 .unwrap_or_else(|e| e.into_inner())
1333 .alloc(shape.held(Data::Seq {
1334 stride,
1335 words: elems.iter().copied().collect(),
1336 }))
1337}
1338
1339pub fn from_copies(shape: &Shape, elems: &[u64]) -> u64 {
1342 retain_elems(shape, elems.iter().copied());
1343 from_words(shape, elems)
1344}
1345
1346pub fn frozen_from_words(elem_words: usize, elems: &[u64]) -> u64 {
1349 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
1350 let h = t.alloc(Held {
1351 data: Data::Seq {
1352 stride: elem_words.max(1),
1353 words: elems.iter().copied().collect(),
1354 },
1355 objs: false,
1356 nested: Nested::NONE,
1357 key_objs: false,
1358 });
1359 if let Some(e) = t.entries[index(h)].as_mut() {
1360 e.frozen = true;
1361 }
1362 h
1363}
1364
1365pub fn frozen_map(entries: Vec<(Key, Vec<u64>)>, default: Option<Vec<u64>>) -> u64 {
1368 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
1369 let h = t.alloc(Held {
1370 data: Data::Map(
1371 entries.into_iter().map(|(k, v)| (k, v.into())).collect(),
1372 default.map(Into::into),
1373 ),
1374 objs: false,
1375 nested: Nested::NONE,
1376 key_objs: false,
1377 });
1378 if let Some(e) = t.entries[index(h)].as_mut() {
1379 e.frozen = true;
1380 }
1381 h
1382}
1383
1384#[derive(Clone, Debug, PartialEq, Eq)]
1386pub enum FrozenData {
1387 Seq {
1388 stride: usize,
1389 words: Vec<u64>,
1390 },
1391 Map {
1392 entries: Vec<(Key, Vec<u64>)>,
1393 default: Option<Vec<u64>>,
1394 },
1395}
1396
1397pub fn frozen_snapshot() -> Result<Vec<FrozenData>, String> {
1404 let t = table().lock().unwrap_or_else(|e| e.into_inner());
1405 t.entries[1..]
1406 .iter()
1407 .enumerate()
1408 .map(|(i, e)| {
1409 let Some(e) = e.as_ref().filter(|e| e.frozen && e.version == 1) else {
1410 return Err(format!(
1411 "collection {} is not a constant of a declaration's initial value",
1412 i + 1
1413 ));
1414 };
1415 Ok(plain(e))
1416 })
1417 .collect()
1418}
1419
1420fn plain(e: &Entry) -> FrozenData {
1421 match &e.data.data {
1422 Data::Seq { stride, words } => FrozenData::Seq {
1423 stride: *stride,
1424 words: words.iter().copied().collect(),
1425 },
1426 Data::Map(m, dflt) => FrozenData::Map {
1427 entries: m.iter().map(|(k, v)| (k.clone(), v.to_vec())).collect(),
1428 default: dflt.as_ref().map(|d| d.to_vec()),
1429 },
1430 }
1431}
1432
1433pub fn frozen_preload(frozen: &[FrozenData]) -> Result<(), String> {
1437 for (i, f) in frozen.iter().enumerate() {
1438 let want = (1u64 << 32) | (i as u64 + 1);
1439 let have = frozen_snapshot_entry(i + 1);
1440 if let Some(have) = have {
1441 if &have != f {
1442 return Err(format!(
1443 "collection {} of the design cannot take its handle: this process \
1444 already made a different one",
1445 i + 1
1446 ));
1447 }
1448 continue;
1449 }
1450 let got = match f {
1451 FrozenData::Seq { stride, words } => frozen_from_words(*stride, words),
1452 FrozenData::Map { entries, default } => frozen_map(entries.clone(), default.clone()),
1453 };
1454 if got != want {
1455 return Err(format!(
1456 "collection {} of the design got handle {got:#x}, not {want:#x}",
1457 i + 1
1458 ));
1459 }
1460 }
1461 Ok(())
1462}
1463
1464fn frozen_snapshot_entry(i: usize) -> Option<FrozenData> {
1466 let t = table().lock().unwrap_or_else(|e| e.into_inner());
1467 t.entries.get(i)?.as_ref().filter(|e| e.frozen).map(plain)
1468}
1469
1470pub fn map_with_values(h: u64, elem_words: usize, flat: &[u64]) -> Option<u64> {
1477 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
1478 let Some(Data::Map(m, dflt)) = t.data(h) else {
1479 return None;
1480 };
1481 if flat.len() != m.len() * elem_words {
1482 return None;
1483 }
1484 let keys: Vec<Key> = m.keys().cloned().collect();
1485 let dflt = dflt.clone();
1486 let map: BTreeMap<Key, Box<[u64]>> = keys
1487 .into_iter()
1488 .zip(flat.chunks(elem_words.max(1)))
1489 .map(|(k, v)| (k, v.into()))
1490 .collect();
1491 Some(t.alloc(Held {
1492 data: Data::Map(map, dflt),
1493 objs: false,
1494 nested: Nested::NONE,
1495 key_objs: false,
1496 }))
1497}
1498
1499pub fn append(shape: &Shape, h: u64, other: u64) -> u64 {
1502 let extra: Vec<u64> = {
1503 let t = table().lock().unwrap_or_else(|e| e.into_inner());
1504 match t.data(other) {
1505 Some(Data::Seq { words, .. }) => words.iter().copied().collect(),
1506 _ => Vec::new(),
1507 }
1508 };
1509 retain_elems(shape, extra.iter().copied());
1510 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
1511 t.modify(
1512 h,
1513 || shape.empty(),
1514 |d| {
1515 if let Data::Seq { words, .. } = &mut d.data {
1516 words.extend(extra);
1517 }
1518 },
1519 )
1520}
1521
1522pub fn slice(shape: &Shape, h: u64, a: i64, b: i64) -> u64 {
1525 let n = size(h) as i64;
1526 let a = a.max(0);
1527 let b = b.min(n - 1);
1528 let stride = shape.elem_words.max(1);
1529 let mut out = VecDeque::new();
1530 if a <= b {
1531 let t = table().lock().unwrap_or_else(|e| e.into_inner());
1532 if let Some(Data::Seq { words, .. }) = t.data(h) {
1533 out.extend(
1534 words
1535 .range(a as usize * stride..(b as usize + 1) * stride)
1536 .copied(),
1537 );
1538 }
1539 }
1540 retain_elems(shape, out.iter().copied());
1541 table()
1542 .lock()
1543 .unwrap_or_else(|e| e.into_inner())
1544 .alloc(shape.held(Data::Seq { stride, words: out }))
1545}
1546
1547pub fn equal(a: u64, b: u64) -> bool {
1549 let t = table().lock().unwrap_or_else(|e| e.into_inner());
1550 match (t.data(a), t.data(b)) {
1551 (None, None) => true,
1552 (Some(d), None) | (None, Some(d)) => d.len() == 0,
1553 (Some(Data::Seq { words: x, .. }), Some(Data::Seq { words: y, .. })) => x == y,
1554 (Some(Data::Map(x, _)), Some(Data::Map(y, _))) => x == y,
1555 _ => false,
1556 }
1557}
1558
1559pub fn neighbor(h: u64, key: Option<&Key>, forward: bool) -> Option<Key> {
1562 let t = table().lock().unwrap_or_else(|e| e.into_inner());
1563 let Some(Data::Map(m, _)) = t.data(h) else {
1564 return None;
1565 };
1566 let found = match (key, forward) {
1567 (None, true) => m.keys().next(),
1568 (None, false) => m.keys().next_back(),
1569 (Some(k), true) => m
1570 .range((Bound::Excluded(k.clone()), Bound::Unbounded))
1571 .next()
1572 .map(|(k, _)| k),
1573 (Some(k), false) => m
1574 .range((Bound::Unbounded, Bound::Excluded(k.clone())))
1575 .next_back()
1576 .map(|(k, _)| k),
1577 };
1578 found.cloned()
1579}
1580
1581pub fn key_at(h: u64, pos: usize) -> Option<Key> {
1584 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
1585 let i = index(h);
1586 let e = t.entries.get_mut(i)?.as_mut()?;
1587 let Data::Map(m, _) = &e.data.data else {
1588 return None;
1589 };
1590 let key = match &e.cursor {
1591 Some((p, k)) if *p == pos => Some(k.clone()),
1592 Some((p, k)) if *p + 1 == pos => m
1593 .range((Bound::Excluded(k.clone()), Bound::Unbounded))
1594 .next()
1595 .map(|(k, _)| k.clone()),
1596 _ => m.keys().nth(pos).cloned(),
1597 };
1598 if let Some(k) = &key {
1599 e.cursor = Some((pos, k.clone()));
1600 }
1601 key
1602}
1603
1604pub fn entry_at(h: u64, pos: usize, out: &mut [u64]) -> Option<Key> {
1607 let key = key_at(h, pos)?;
1608 lookup(h, &key, out);
1609 Some(key)
1610}
1611
1612pub fn permute(shape: &Shape, h: u64, order: &[usize]) -> u64 {
1615 let old = elements(h);
1616 if old.len() != order.len() || old.is_empty() {
1617 return h;
1618 }
1619 let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
1620 let new = t.modify(
1621 h,
1622 || shape.empty(),
1623 |d| {
1624 if let Data::Seq { words, .. } = &mut d.data {
1626 words.clear();
1627 for &k in order {
1628 words.extend(old[k].iter().copied());
1629 }
1630 }
1631 },
1632 );
1633 t.refs_outdated(index(new), 0);
1638 new
1639}
1640
1641pub fn elements(h: u64) -> Vec<Vec<u64>> {
1644 let t = table().lock().unwrap_or_else(|e| e.into_inner());
1645 match t.data(h) {
1646 Some(Data::Seq { stride, words }) => words
1647 .iter()
1648 .copied()
1649 .collect::<Vec<_>>()
1650 .chunks(*stride)
1651 .map(<[u64]>::to_vec)
1652 .collect(),
1653 Some(Data::Map(m, _)) => m.values().map(|v| v.to_vec()).collect(),
1654 None => Vec::new(),
1655 }
1656}
1657
1658pub fn keys(h: u64) -> Vec<Key> {
1660 let t = table().lock().unwrap_or_else(|e| e.into_inner());
1661 match t.data(h) {
1662 Some(Data::Map(m, _)) => m.keys().cloned().collect(),
1663 _ => Vec::new(),
1664 }
1665}
1666
1667#[cfg(test)]
1668mod tests {
1669 use super::*;
1670
1671 const Q: Shape = Shape {
1672 elem_words: 1,
1673 assoc: false,
1674 key: KeyKind::Str,
1675 obj: false,
1676 nested: Nested::NONE,
1677 };
1678
1679 #[test]
1680 fn a_queue_pushes_pops_and_changes_handle_on_every_change() {
1681 let h = push(&Q, 0, &[3], false);
1682 let h2 = push(&Q, h, &[4], false);
1683 assert_ne!(h, h2, "each change is a new handle value");
1684 let h3 = push(&Q, h2, &[1], true);
1685 assert_eq!(size(h3), 3);
1686 let mut out = [0];
1687 assert!(get(h3, 2, &mut out));
1688 assert_eq!(out, [4]);
1689 let (h4, ok) = pop(&Q, h3, &mut out, true);
1690 assert!(ok);
1691 assert_eq!(out, [1]);
1692 assert_eq!(size(h4), 2);
1693 }
1694
1695 #[test]
1696 fn clone_deep_copies_inner_collections_and_equal_nest_compares_contents() {
1697 const OUTER: Shape = Shape {
1698 elem_words: 2,
1699 assoc: false,
1700 key: KeyKind::Str,
1701 obj: false,
1702 nested: Nested::NONE,
1703 };
1704 let nest = Nest {
1705 slots: vec![(0, Nest::default())],
1706 };
1707 let inner = push(&Q, push(&Q, 0, &[1], false), &[2], false);
1708 let outer = push(&OUTER, 0, &[inner, 0], false);
1709 let mut minted = Vec::new();
1710 let copy = clone_deep(outer, &nest, &mut minted);
1711 let grown = push(&Q, inner, &[3], false);
1714 let outer = set(&OUTER, outer, 0, &[grown, 0], true);
1715 let mut got = [0, 0];
1716 assert!(get(copy, 0, &mut got));
1717 assert_eq!(size(got[0]), 2, "the copy keeps the old inner contents");
1718 assert!(!equal_nest(outer, copy, &nest), "contents differ");
1719 let again = clone_deep(outer, &nest, &mut minted);
1720 assert!(equal_nest(outer, again, &nest));
1721 minted.iter().for_each(|&h| release(h));
1722 }
1723
1724 fn queue_of(vals: &[u64]) -> u64 {
1725 vals.iter().fold(0, |h, v| push(&Q, h, &[*v], false))
1726 }
1727
1728 fn words(h: u64) -> Vec<u64> {
1729 (0..size(h) as i64)
1730 .map(|i| {
1731 let mut o = [0];
1732 get(h, i, &mut o);
1733 o[0]
1734 })
1735 .collect()
1736 }
1737
1738 #[test]
1739 fn an_element_reference_follows_other_elements_and_writes_through() {
1740 let h = queue_of(&[1, 2, 3]);
1741 let id = ref_open(h, 1);
1742 assert_ne!(id, 0);
1743 let mut out = [0];
1744 assert!(ref_get(id, &mut out));
1745 assert_eq!(out, [2]);
1746 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));
1750 assert_eq!(out, [2]);
1751 ref_put(id, &[10]);
1752 assert_eq!(words(h), [8, 1, 10, 3]);
1753 let h = set(&Q, h, 2, &[11], true);
1755 assert!(ref_get(id, &mut out));
1756 assert_eq!(out, [11]);
1757 ref_close(id);
1758 assert!(!ref_get(id, &mut out), "a closed reference is gone");
1759 assert_eq!(words(h), [8, 1, 11, 3]);
1760 }
1761
1762 #[test]
1763 fn a_part_reference_reads_and_writes_only_its_bits() {
1764 let h = queue_of(&[0x0000_0F00_AABB_CCDD, 7]);
1766 let id = ref_open(h, 0);
1767 let mut out = [u64::MAX];
1768 assert!(ref_get_part(id, 8, 8, 32, &mut out));
1769 assert_eq!(out, [0x0FCC]);
1771 ref_put_part(id, 8, 8, 32, &[0x01_55]);
1772 assert_eq!(words(h), [0x0000_0100_AABB_55DD, 7]);
1773 assert!(ref_get_part(id, 0, 32, 0, &mut out));
1775 assert_eq!(out, [0x0000_0100_AABB_55DD]);
1776 ref_close(id);
1777 assert!(!ref_get_part(id, 8, 8, 32, &mut out));
1778 }
1779
1780 #[test]
1781 fn an_outdated_element_reference_drops_its_write_and_keeps_its_id() {
1782 let mut out = [0];
1785 let h = queue_of(&[1, 2, 3]);
1786 let id = ref_open(h, 1);
1787 let h = delete_at(&Q, h, 1);
1788 assert!(!ref_get(id, &mut out));
1789 let other = ref_open(h, 0);
1791 assert_ne!(other, id);
1792 ref_put(id, &[10]);
1793 assert_eq!(words(h), [1, 3]);
1794 ref_close(id);
1795 ref_close(other);
1796
1797 let h = queue_of(&[1, 2, 3]);
1798 let id = ref_open(h, 2);
1799 let (h, _) = pop(&Q, h, &mut out, false);
1800 ref_put(id, &[10]);
1801 assert_eq!(words(h), [1, 2]);
1802 ref_close(id);
1803
1804 let h = queue_of(&[1, 2, 3]);
1805 let id = ref_open(h, 2);
1806 let h = truncate(&Q, h, 2);
1807 ref_put(id, &[10]);
1808 assert_eq!(words(h), [1, 2]);
1809 ref_close(id);
1810
1811 let h = queue_of(&[1, 2, 3]);
1812 let id = ref_open(h, 0);
1813 let h = clear(&Q, h);
1814 let h = push(&Q, h, &[5], false);
1815 ref_put(id, &[10]);
1816 assert_eq!(words(h), [5]);
1817 ref_close(id);
1818
1819 let h = queue_of(&[1, 2, 3]);
1821 let id = ref_open(h, 0);
1822 release(h);
1823 let other = queue_of(&[7, 8, 9]);
1824 ref_put(id, &[10]);
1825 assert_eq!(words(other), [7, 8, 9]);
1826 assert!(!ref_get(id, &mut out));
1827 ref_close(id);
1828 }
1829
1830 #[test]
1831 fn a_reference_outside_the_collection_is_never_open() {
1832 let h = queue_of(&[1]);
1833 assert_eq!(ref_open(h, 1), 0);
1834 assert_eq!(ref_open(h, -1), 0);
1835 assert_eq!(ref_open(0, 0), 0);
1836 ref_put(0, &[5]);
1837 assert_eq!(words(h), [1]);
1838 }
1839
1840 #[test]
1841 fn a_reference_survives_a_frozen_values_first_write() {
1842 let f = frozen_from_words(1, &[1, 2]);
1843 let f = ref_own(&Q, f);
1844 let id = ref_open(f, 1);
1845 let g = insert(&Q, f, 0, &[0]);
1846 ref_put(id, &[5]);
1847 assert_eq!(words(g), [0, 1, 5]);
1848 ref_close(id);
1849 }
1850
1851 #[test]
1852 fn a_clone_is_a_copy_on_write_value() {
1853 let a = push(&Q, 0, &[7], false);
1854 let b = clone(a);
1855 let b2 = set(&Q, b, 0, &[9], true);
1856 let mut out = [0];
1857 get(a, 0, &mut out);
1858 assert_eq!(out, [7], "changing the copy leaves the original");
1859 get(b2, 0, &mut out);
1860 assert_eq!(out, [9]);
1861 }
1862
1863 #[test]
1864 fn a_frozen_value_is_shared_and_never_changed_in_place() {
1865 let f = frozen_from_words(1, &[1, 2]);
1866 assert_eq!(clone(f), f, "a constant needs no copy");
1867 let a = push(&Q, f, &[3], false);
1868 assert_ne!(index(a), index(f), "a change makes a new entry");
1869 assert_eq!(size(f), 2);
1870 assert_eq!(size(a), 3);
1871 release(f);
1872 assert_eq!(size(f), 2, "a constant is never freed");
1873 }
1874
1875 #[test]
1876 fn associative_keys_are_ordered_and_walkable() {
1877 let s = Shape {
1878 elem_words: 1,
1879 assoc: true,
1880 key: KeyKind::Int {
1881 width: 8,
1882 signed: true,
1883 },
1884 obj: false,
1885 nested: Nested::NONE,
1886 };
1887 let mut h = 0;
1888 for k in [5i128, -3, 2] {
1889 h = store(&s, h, Key::Int(k), &[k as u64]);
1890 }
1891 assert_eq!(neighbor(h, None, true), Some(Key::Int(-3)));
1892 assert_eq!(neighbor(h, Some(&Key::Int(2)), true), Some(Key::Int(5)));
1893 assert_eq!(neighbor(h, Some(&Key::Int(5)), true), None);
1894 assert_eq!(key_at(h, 0), Some(Key::Int(-3)));
1895 assert_eq!(key_at(h, 1), Some(Key::Int(2)));
1896 assert_eq!(key_at(h, 2), Some(Key::Int(5)));
1897 assert_eq!(s.key_from_bits(&[0xfd]), Some(Key::Int(-3)));
1898 assert_eq!(s.key_from_bits(&[0x1fd]), None, "an unknown bit");
1899 }
1900
1901 const OQ: Shape = Shape {
1908 elem_words: 2,
1909 assoc: false,
1910 key: KeyKind::Str,
1911 obj: true,
1912 nested: Nested::NONE,
1913 };
1914
1915 fn oa() -> Shape {
1916 Shape {
1917 elem_words: 2,
1918 assoc: true,
1919 key: KeyKind::Int {
1920 width: 8,
1921 signed: true,
1922 },
1923 obj: true,
1924 nested: Nested::NONE,
1925 }
1926 }
1927
1928 fn obj(template: u32) -> u64 {
1930 crate::objects::alloc(crate::netlist::ClassTemplateId(template), 1)
1931 }
1932
1933 fn rc(h: u64) -> Option<u32> {
1934 crate::objects::refcount(h)
1935 }
1936
1937 #[test]
1938 fn a_pushed_object_element_takes_the_callers_reference() {
1939 let a = obj(1013);
1940 let q = push(&OQ, 0, &[a, 0], false);
1941 assert_eq!(rc(a), Some(1), "the queue owns the one reference");
1942 release(q);
1943 assert_eq!(rc(a), None, "releasing the queue frees what it alone held");
1944 }
1945
1946 #[test]
1947 fn overwriting_deleting_and_clearing_release_the_old_element() {
1948 let (a, b, c) = (obj(1014), obj(1014), obj(1014));
1949 crate::objects::retain(a);
1950 crate::objects::retain(b);
1951 crate::objects::retain(c);
1952 let mut q = push(&OQ, 0, &[a, 0], false);
1954 q = push(&OQ, q, &[b, 0], false);
1955 q = push(&OQ, q, &[c, 0], false);
1956 assert_eq!((rc(a), rc(b), rc(c)), (Some(2), Some(2), Some(2)));
1957 crate::objects::retain(b);
1960 q = set(&OQ, q, 0, &[b, 0], true);
1961 assert_eq!(rc(a), Some(1), "an overwritten element is released");
1962 assert_eq!(rc(b), Some(3));
1963 q = delete_at(&OQ, q, 0);
1964 assert_eq!(rc(b), Some(2), "a deleted element is released");
1965 q = clear(&OQ, q);
1966 assert_eq!(rc(b), Some(1));
1967 assert_eq!(rc(c), Some(1), "clear releases every element");
1968 assert_eq!(size(q), 0);
1969 for h in [a, b, c] {
1970 crate::objects::release(h);
1971 assert_eq!(rc(h), None);
1972 }
1973 release(q);
1974 }
1975
1976 #[test]
1977 fn a_pop_hands_its_reference_to_the_caller() {
1978 let a = obj(1015);
1979 let q = push(&OQ, 0, &[a, 0], false);
1980 let mut out = [0, 0];
1981 let (q, ok) = pop(&OQ, q, &mut out, true);
1982 assert!(ok);
1983 assert_eq!(out[0], a);
1984 assert_eq!(rc(a), Some(1), "the reference moved, it was not dropped");
1985 crate::objects::release(out[0]);
1986 assert_eq!(rc(a), None);
1987 release(q);
1988 }
1989
1990 fn pair_q() -> Shape {
1993 let mut nested = Nested::NONE;
1994 nested.n = 2;
1995 nested.at[1] = 64;
1996 Shape {
1997 elem_words: 4,
1998 assoc: false,
1999 key: KeyKind::Str,
2000 obj: false,
2001 nested,
2002 }
2003 }
2004
2005 #[test]
2006 fn handles_nested_in_an_element_are_owned_and_released_with_it() {
2007 let s = pair_q();
2008 let (a, b, c, d) = (obj(1018), obj(1018), obj(1018), obj(1018));
2009 let mut q = push(&s, 0, &[a, b, 0, 0], false);
2010 q = push(&s, q, &[c, d, 0, 0], false);
2011 assert_eq!(
2012 (rc(a), rc(b), rc(c), rc(d)),
2013 (Some(1), Some(1), Some(1), Some(1))
2014 );
2015 let copy = clone(q);
2017 let copy = delete_at(&s, copy, 1);
2018 assert_eq!(
2019 (rc(a), rc(c)),
2020 (Some(2), Some(1)),
2021 "the copy retained element 0"
2022 );
2023 assert_eq!(rc(d), Some(1));
2024 crate::objects::retain(c);
2027 crate::objects::retain(d);
2028 let q = set(&s, q, 0, &[c, d, 0, 0], true);
2029 assert_eq!((rc(a), rc(b)), (Some(1), Some(1)));
2030 release(copy);
2031 assert_eq!((rc(a), rc(b)), (None, None), "the copy's drop frees them");
2032 let mut out = [0; 4];
2034 let (q, ok) = pop(&s, q, &mut out, true);
2035 assert!(ok);
2036 assert_eq!((out[0], out[1]), (c, d));
2037 assert_eq!((rc(c), rc(d)), (Some(2), Some(2)));
2038 release(q);
2039 assert_eq!((rc(c), rc(d)), (Some(1), Some(1)));
2040 crate::objects::release(c);
2041 crate::objects::release(d);
2042 assert_eq!((rc(c), rc(d)), (None, None));
2043 }
2044
2045 #[test]
2046 fn an_ignored_write_gives_back_the_reference_it_was_handed() {
2047 let (a, b, c) = (obj(1016), obj(1016), obj(1016));
2048 let q = push(&OQ, 0, &[c, 0], false);
2049 let q = set(&OQ, q, 5, &[a, 0], true);
2050 assert_eq!(rc(a), None, "an out-of-range set releases the value");
2051 let q = insert(&OQ, q, -1, &[b, 0]);
2052 assert_eq!(rc(b), None, "an out-of-range insert releases the value");
2053 assert_eq!(rc(c), Some(1), "the element already there is untouched");
2054 release(q);
2055 assert_eq!(rc(c), None);
2056 }
2057
2058 #[test]
2059 fn a_copy_on_write_clone_takes_its_own_reference_per_element() {
2060 let a = obj(1017);
2061 let q = push(&OQ, 0, &[a, 0], false);
2062 let copy = clone(q);
2063 assert_eq!(rc(a), Some(1), "an unchanged clone shares the references");
2064 let b = obj(1017);
2065 let copy = push(&OQ, copy, &[b, 0], false);
2066 assert_eq!(rc(a), Some(2), "unsharing the copy retains each element");
2067 release(q);
2068 assert_eq!(rc(a), Some(1), "the original's holder let go of its own");
2069 release(copy);
2070 assert_eq!(rc(a), None);
2071 assert_eq!(rc(b), None);
2072 }
2073
2074 #[test]
2075 fn resized_append_slice_and_from_copies_retain_what_they_copy() {
2076 let (a, b) = (obj(1018), obj(1018));
2077 let q = push(&OQ, push(&OQ, 0, &[a, 0], false), &[b, 0], false);
2078 assert_eq!((rc(a), rc(b)), (Some(1), Some(1)));
2079 let grown = resized(&OQ, q, 3, &[a, 0]);
2080 assert_eq!((rc(a), rc(b)), (Some(3), Some(2)));
2083 let sl = slice(&OQ, q, 1, 1);
2084 assert_eq!(rc(b), Some(3));
2085 let ap = append(&OQ, 0, q);
2086 assert_eq!((rc(a), rc(b)), (Some(4), Some(4)));
2087 let fc = from_copies(&OQ, &[a, 0, b, 0]);
2088 assert_eq!((rc(a), rc(b)), (Some(5), Some(5)));
2089 for h in [q, grown, sl, ap, fc] {
2090 release(h);
2091 }
2092 assert_eq!(
2093 (rc(a), rc(b)),
2094 (None, None),
2095 "no holder left, nothing leaks"
2096 );
2097 }
2098
2099 #[test]
2100 fn an_associative_array_owns_values_and_its_default() {
2101 let (a, b, d) = (obj(1019), obj(1019), obj(1019));
2102 let s = oa();
2103 let mut h = store(&s, 0, Key::Int(1), &[a, 0]);
2104 crate::objects::retain(a);
2105 h = store(&s, h, Key::Int(2), &[a, 0]);
2106 assert_eq!(rc(a), Some(2), "two keys, two references");
2107 h = store(&s, h, Key::Int(1), &[b, 0]);
2108 assert_eq!(rc(a), Some(1), "replacing a value releases the old one");
2109 h = delete_key(&s, h, &Key::Int(2));
2110 assert_eq!(rc(a), None, "deleting a key releases its value");
2111 h = delete_key(&s, h, &Key::Int(99));
2112 assert_eq!(rc(b), Some(1), "deleting an absent key changes nothing");
2113 h = set_default(&s, h, &[d, 0]);
2114 assert_eq!(rc(d), Some(1));
2115 h = clear(&s, h);
2116 assert_eq!(rc(b), None);
2117 assert_eq!(rc(d), Some(1), "clear keeps the default's reference");
2118 release(h);
2119 assert_eq!(rc(d), None, "freeing the array frees its default");
2120 }
2121
2122 #[test]
2126 fn a_handle_keyed_map_owns_its_keys() {
2127 let (k1, k2) = (obj(1021), obj(1021));
2128 let s = Shape {
2129 elem_words: 1,
2130 assoc: true,
2131 key: KeyKind::Obj,
2132 obj: false,
2133 nested: Nested::NONE,
2134 };
2135 let key = |k: u64| Key::Int(i128::from(k));
2136 let mut h = store(&s, 0, key(k1), &[1]);
2137 assert_eq!(rc(k1), Some(2), "a new key takes its own reference");
2138 h = store(&s, h, key(k1), &[2]);
2139 assert_eq!(rc(k1), Some(2), "re-storing an existing key adds none");
2140 h = store(&s, h, key(k2), &[3]);
2141 let c = clone(h);
2142 let c = store(&s, c, key(k2), &[4]);
2143 assert_eq!(rc(k1), Some(3), "an unshared copy retains each key");
2144 h = delete_key(&s, h, &key(k1));
2145 assert_eq!(rc(k1), Some(2), "deleting a key releases it");
2146 h = clear(&s, h);
2147 assert_eq!(rc(k2), Some(2), "clear releases every key");
2148 release(h);
2149 release(c);
2150 assert_eq!(rc(k1), Some(1), "freeing the copy releases its keys");
2151 assert_eq!(rc(k2), Some(1));
2152 crate::objects::release(k1);
2153 crate::objects::release(k2);
2154 }
2155
2156 #[test]
2157 fn a_permutation_moves_references_without_changing_counts() {
2158 let (a, b) = (obj(1020), obj(1020));
2159 let q = push(&OQ, push(&OQ, 0, &[a, 0], false), &[b, 0], false);
2160 let q = permute(&OQ, q, &[1, 0]);
2161 let mut out = [0, 0];
2162 assert!(get(q, 0, &mut out));
2163 assert_eq!(out[0], b);
2164 assert_eq!((rc(a), rc(b)), (Some(1), Some(1)));
2165 release(q);
2166 assert_eq!((rc(a), rc(b)), (None, None));
2167 }
2168
2169 #[test]
2175 fn frozen_snapshot_refuses_a_live_collection() {
2176 let live = from_words(&Q, &[1, 2]);
2177 let why = frozen_snapshot().expect_err("a live collection cannot be frozen into an image");
2178 assert!(why.contains("not a constant"), "{why}");
2179 release(live);
2180 }
2181}