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