1use std::cmp::Ordering;
53
54use yo_common::num;
55use yo_common::{Code, Error, Result};
56
57use crate::frozen::{self, Broken};
58
59pub const SLICE_SIZE: u64 = 4096;
65
66const SLICE_BITS: u32 = SLICE_SIZE.trailing_zeros();
68
69const SPARSE_MAX: usize = 10;
74
75const SPARSE_MIN: usize = 5;
81
82const FORM_SLICES: u8 = 1;
84const HAS_INSERT: u8 = 0x80;
86const LAYOUT_SPARSE: u8 = 1;
88const LAYOUT_DENSE: u8 = 2;
90
91pub const INDEX_MAX: u64 = u64::MAX - 1;
99
100pub const ELEMENT_MAX: usize = num::DOUBLE_MAX + 2;
105
106#[derive(Debug, Clone, Copy, PartialEq)]
113pub enum Element<'a> {
114 Int(i64),
116 Float(f64),
118 Str(&'a [u8]),
120 Short(Short),
123}
124
125impl<'a> Element<'a> {
126 pub fn text<'b>(&'b self, buf: &'b mut [u8; ELEMENT_MAX]) -> &'b [u8]
135 where
136 'a: 'b,
137 {
138 match *self {
139 Element::Str(s) => s,
141 Element::Short(ref s) => s.as_bytes(),
142 Element::Int(i) => {
143 let mut digits = [0u8; num::DIGITS_MAX];
144 let text = num::i64_digits(&mut digits, i);
145 let n = text.len();
146 buf[..n].copy_from_slice(text);
147 &buf[..n]
148 }
149 Element::Float(d) => {
150 let mut wide = [0u8; num::DOUBLE_MAX];
151 let text = num::write_double(&mut wide, d);
152 let mut n = text.len();
153 buf[..n].copy_from_slice(text);
154 if !text.iter().any(|&c| c == b'.' || c == b'e' || c == b'E') {
160 buf[n] = b'.';
161 buf[n + 1] = b'0';
162 n += 2;
163 }
164 &buf[..n]
165 }
166 }
167 }
168}
169
170#[derive(Clone, Copy, PartialEq, Eq)]
178pub struct Short {
179 buf: [u8; INLINE_MAX],
180 len: u8,
181}
182
183impl Short {
184 #[must_use]
186 pub fn as_bytes(&self) -> &[u8] {
187 &self.buf[..usize::from(self.len)]
188 }
189}
190
191impl core::fmt::Debug for Short {
192 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
193 write!(f, "{:?}", String::from_utf8_lossy(self.as_bytes()))
194 }
195}
196
197#[derive(Debug, Clone, Copy, PartialEq, Eq)]
216struct Word(u64);
217
218const INLINE_MAX: usize = 7;
220
221const BLOB_MAX: usize = u32::MAX as usize;
223
224const VALUE_MAX: usize = (1 << 30) - 1;
231
232const TAG_MASK: u64 = 0b11;
233const TAG_BLOB: u64 = 0;
234const TAG_INT: u64 = 1;
235const TAG_FLOAT: u64 = 2;
236const TAG_STR: u64 = 3;
237
238const INT_LO: i64 = -(1 << 61);
241const INT_HI: i64 = (1 << 61) - 1;
242
243impl Word {
244 const EMPTY: Word = Word(0);
246
247 const fn is_empty(self) -> bool {
248 self.0 == 0
249 }
250
251 const fn tag(self) -> u64 {
252 self.0 & TAG_MASK
253 }
254
255 const fn from_int(i: i64) -> Word {
256 Word(((i as u64) << 2) | TAG_INT)
257 }
258
259 const fn to_int(self) -> i64 {
260 (self.0 as i64) >> 2
262 }
263
264 const fn from_float_bits(bits: u64) -> Word {
265 Word((bits & !TAG_MASK) | TAG_FLOAT)
266 }
267
268 const fn to_float(self) -> f64 {
269 f64::from_bits(self.0 & !TAG_MASK)
270 }
271
272 fn from_short(s: &[u8]) -> Word {
273 let mut v = TAG_STR | ((s.len() as u64) << 2);
274 for (i, &b) in s.iter().enumerate() {
275 v |= u64::from(b) << (8 * (i + 1));
276 }
277 Word(v)
278 }
279
280 const fn short_len(self) -> usize {
281 ((self.0 >> 2) & 0b111) as usize
282 }
283
284 fn to_short(self) -> Short {
285 let n = self.short_len();
286 let mut buf = [0u8; INLINE_MAX];
287 for (i, out) in buf.iter_mut().take(n).enumerate() {
288 *out = ((self.0 >> (8 * (i + 1))) & 0xff) as u8;
289 }
290 Short { buf, len: n as u8 }
291 }
292
293 const fn from_blob(start: usize, len: usize) -> Word {
294 Word(((start as u64) << 32) | ((len as u64) << 2) | TAG_BLOB)
295 }
296
297 const fn blob_span(self) -> (usize, usize) {
298 let start = (self.0 >> 32) as usize;
299 let len = ((self.0 >> 2) & 0x3fff_ffff) as usize;
300 (start, len)
301 }
302}
303
304#[derive(Debug, Clone)]
307struct Slice {
308 count: u16,
311 layout: Layout,
312}
313
314#[derive(Debug, Clone)]
319enum Layout {
320 Sparse { offs: Vec<u16>, words: Vec<Word> },
325 Dense { offset: u16, words: Vec<Word> },
333}
334
335impl Slice {
336 fn words_mut(&mut self) -> &mut [Word] {
339 match &mut self.layout {
340 Layout::Sparse { words, .. } | Layout::Dense { words, .. } => words,
341 }
342 }
343
344 fn words(&self) -> &[Word] {
346 match &self.layout {
347 Layout::Sparse { words, .. } | Layout::Dense { words, .. } => words,
348 }
349 }
350
351 fn high(&self) -> u16 {
353 match &self.layout {
354 Layout::Sparse { offs, .. } => *offs.last().expect("a slice is never empty"),
355 Layout::Dense { offset, words } => offset + (words.len() as u16) - 1,
357 }
358 }
359
360 fn get(&self, off: u16) -> Word {
361 match &self.layout {
362 Layout::Sparse { offs, words } => match offs.binary_search(&off) {
363 Ok(at) => words[at],
364 Err(_) => Word::EMPTY,
365 },
366 Layout::Dense { offset, words } => {
367 if off < *offset {
368 return Word::EMPTY;
369 }
370 let at = usize::from(off - offset);
371 words.get(at).copied().unwrap_or(Word::EMPTY)
372 }
373 }
374 }
375
376 fn put(&mut self, off: u16, w: Word) -> Word {
378 let old = match &mut self.layout {
379 Layout::Sparse { offs, words } => match offs.binary_search(&off) {
380 Ok(at) => std::mem::replace(&mut words[at], w),
381 Err(at) => {
382 offs.insert(at, off);
383 words.insert(at, w);
384 Word::EMPTY
385 }
386 },
387 Layout::Dense { offset, words } => {
388 if off < *offset {
389 let gap = usize::from(*offset - off);
394 words.splice(0..0, std::iter::repeat_n(Word::EMPTY, gap));
395 *offset = off;
396 std::mem::replace(&mut words[0], w)
397 } else {
398 let at = usize::from(off - *offset);
399 if at >= words.len() {
400 words.resize(at + 1, Word::EMPTY);
401 }
402 std::mem::replace(&mut words[at], w)
403 }
404 }
405 };
406 if old.is_empty() {
407 self.count += 1;
408 }
409 old
410 }
411
412 fn take(&mut self, off: u16) -> Word {
414 let old = match &mut self.layout {
415 Layout::Sparse { offs, words } => match offs.binary_search(&off) {
416 Ok(at) => {
417 offs.remove(at);
418 words.remove(at)
419 }
420 Err(_) => Word::EMPTY,
421 },
422 Layout::Dense { offset, words } => {
423 if off < *offset {
424 Word::EMPTY
425 } else {
426 let at = usize::from(off - *offset);
427 match words.get_mut(at) {
428 Some(slot) => std::mem::replace(slot, Word::EMPTY),
429 None => Word::EMPTY,
430 }
431 }
432 }
433 };
434 if !old.is_empty() {
435 self.count -= 1;
436 self.trim();
437 }
438 old
439 }
440
441 fn trim(&mut self) {
447 let Layout::Dense { offset, words } = &mut self.layout else {
448 return;
449 };
450 while words.last().is_some_and(|w| w.is_empty()) {
451 words.pop();
452 }
453 let lead = words.iter().take_while(|w| w.is_empty()).count();
454 if lead > 0 {
455 words.drain(..lead);
456 *offset += lead as u16;
457 }
458 }
459
460 fn span(&self) -> usize {
462 match &self.layout {
463 Layout::Sparse { offs, .. } => match (offs.first(), offs.last()) {
464 (Some(lo), Some(hi)) => usize::from(hi - lo) + 1,
465 _ => 0,
466 },
467 Layout::Dense { words, .. } => words.len(),
468 }
469 }
470
471 fn rebalance(&mut self) {
480 let count = usize::from(self.count);
481 match &self.layout {
482 Layout::Sparse { .. } => {
483 if count > SPARSE_MAX && self.span() <= count * 2 {
484 self.make_dense();
485 }
486 }
487 Layout::Dense { .. } => {
488 if count <= SPARSE_MIN || self.span() > count * 4 {
489 self.make_sparse();
490 }
491 }
492 }
493 }
494
495 fn make_dense(&mut self) {
496 let Layout::Sparse { offs, words } = &self.layout else {
497 return;
498 };
499 let base = offs[0];
500 let span = self.span();
501 let mut window = vec![Word::EMPTY; span];
502 for (&off, &w) in offs.iter().zip(words) {
503 window[usize::from(off - base)] = w;
504 }
505 self.layout = Layout::Dense {
506 offset: base,
507 words: window,
508 };
509 }
510
511 fn make_sparse(&mut self) {
512 let Layout::Dense { offset, words } = &self.layout else {
513 return;
514 };
515 let mut offs = Vec::with_capacity(usize::from(self.count));
516 let mut vals = Vec::with_capacity(usize::from(self.count));
517 for (i, &w) in words.iter().enumerate() {
518 if !w.is_empty() {
519 offs.push(offset + (i as u16));
520 vals.push(w);
521 }
522 }
523 self.layout = Layout::Sparse { offs, words: vals };
524 }
525
526 fn memory_bytes(&self) -> usize {
527 match &self.layout {
528 Layout::Sparse { offs, words } => {
529 offs.capacity() * 2 + words.capacity() * size_of::<Word>()
530 }
531 Layout::Dense { words, .. } => words.capacity() * size_of::<Word>(),
532 }
533 }
534
535 fn window<F>(&self, from: u16, to: u16, reverse: bool, f: &mut F) -> bool
546 where
547 F: FnMut(u16, Word) -> bool,
548 {
549 match &self.layout {
550 Layout::Sparse { offs, words } => {
551 let a = offs.partition_point(|&o| o < from);
555 let b = offs.partition_point(|&o| o <= to);
556 if reverse {
557 for i in (a..b).rev() {
558 if !f(offs[i], words[i]) {
559 return false;
560 }
561 }
562 } else {
563 for i in a..b {
564 if !f(offs[i], words[i]) {
565 return false;
566 }
567 }
568 }
569 }
570 Layout::Dense { offset, words } => {
571 let base = *offset;
572 let end = base + (words.len() as u16) - 1;
573 if to < base || from > end {
574 return true;
575 }
576 let a = usize::from(from.max(base) - base);
577 let b = usize::from(to.min(end) - base);
578 let window = &words[a..=b];
579 let at = |i: usize| base + ((a + i) as u16);
580 if reverse {
581 for (i, w) in window.iter().enumerate().rev() {
582 if !w.is_empty() && !f(at(i), *w) {
583 return false;
584 }
585 }
586 } else {
587 for (i, w) in window.iter().enumerate() {
588 if !w.is_empty() && !f(at(i), *w) {
589 return false;
590 }
591 }
592 }
593 }
594 }
595 true
596 }
597}
598
599#[derive(Debug, Clone, Default)]
601pub struct Array {
602 slices: Vec<(u64, Slice)>,
605 blob: Vec<u8>,
607 dead: usize,
609 count: u64,
612 insert: Option<u64>,
622}
623
624const COMPACT_MIN: usize = 4096;
631
632impl Array {
633 #[must_use]
635 pub fn new() -> Array {
636 Array::default()
637 }
638
639 #[must_use]
644 pub fn len(&self) -> u64 {
645 match self.slices.last() {
646 Some((id, slice)) => id * SLICE_SIZE + u64::from(slice.high()) + 1,
647 None => 0,
648 }
649 }
650
651 #[must_use]
653 pub const fn count(&self) -> u64 {
654 self.count
655 }
656
657 #[must_use]
659 pub const fn is_empty(&self) -> bool {
660 self.count == 0
661 }
662
663 #[must_use]
668 pub fn get(&self, idx: u64) -> Option<Element<'_>> {
669 let (id, off) = split(idx);
670 let at = self.find(id).ok()?;
671 let w = self.slices[at].1.get(off);
672 self.decode(w)
673 }
674
675 pub fn set(&mut self, idx: u64, val: &[u8]) -> Result<bool> {
686 let w = self.encode(val)?;
687 let (id, off) = split(idx);
688 let at = match self.find(id) {
689 Ok(at) => at,
690 Err(at) => {
691 self.slices.insert(
692 at,
693 (
694 id,
695 Slice {
696 count: 0,
697 layout: Layout::Sparse {
698 offs: Vec::new(),
699 words: Vec::new(),
700 },
701 },
702 ),
703 );
704 at
705 }
706 };
707 let old = self.slices[at].1.put(off, w);
708 self.slices[at].1.rebalance();
709 self.retire(old);
710 self.maybe_compact();
711 if old.is_empty() {
712 self.count += 1;
713 Ok(true)
714 } else {
715 Ok(false)
716 }
717 }
718
719 pub fn del(&mut self, idx: u64) -> bool {
721 let (id, off) = split(idx);
722 let Ok(at) = self.find(id) else {
723 return false;
724 };
725 let old = self.slices[at].1.take(off);
726 if old.is_empty() {
727 return false;
728 }
729 self.retire(old);
730 self.count -= 1;
731 if self.slices[at].1.count == 0 {
732 self.slices.remove(at);
733 } else {
734 self.slices[at].1.rebalance();
735 }
736 self.maybe_compact();
737 true
738 }
739
740 pub fn delete_range(&mut self, lo: u64, hi: u64) -> u64 {
747 if lo > hi {
748 return 0;
749 }
750 let (lo_id, lo_off) = split(lo);
751 let (hi_id, hi_off) = split(hi);
752 let first = match self.find(lo_id) {
753 Ok(at) | Err(at) => at,
754 };
755 let mut gone = 0;
756 let mut at = first;
757 while at < self.slices.len() && self.slices[at].0 <= hi_id {
758 let id = self.slices[at].0;
759 let from = if id == lo_id { lo_off } else { 0 };
762 let to = if id == hi_id {
763 hi_off
764 } else {
765 (SLICE_SIZE - 1) as u16
766 };
767 gone += self.clear_within(at, from, to);
768 if self.slices[at].1.count == 0 {
769 self.slices.remove(at);
770 } else {
771 self.slices[at].1.rebalance();
772 at += 1;
773 }
774 }
775 self.count -= gone;
776 self.maybe_compact();
777 self.maybe_compact_slices();
778 gone
779 }
780
781 #[must_use]
787 pub const fn next_index(&self) -> Option<u64> {
788 match self.insert {
789 None => Some(0),
790 Some(i) if i >= INDEX_MAX => None,
791 Some(i) => Some(i + 1),
792 }
793 }
794
795 pub const fn seek(&mut self, idx: u64) {
802 self.insert = if idx == 0 { None } else { Some(idx - 1) };
803 }
804
805 pub fn append<'v>(&mut self, values: impl Iterator<Item = &'v [u8]> + Clone) -> Result<u64> {
814 let n = values.clone().count() as u64;
815 let over = || Error::new(Code::Invalid, INSERT_OVERFLOW);
816 let start = self.next_index().ok_or_else(over)?;
817 if n == 0 {
818 return Ok(self.insert.unwrap_or(0));
819 }
820 let last = start.checked_add(n - 1).filter(|l| *l <= INDEX_MAX);
821 let last = last.ok_or_else(over)?;
822 for (i, v) in values.enumerate() {
823 self.set(start + i as u64, v)?;
824 }
825 self.insert = Some(last);
826 Ok(last)
827 }
828
829 pub fn ring<'v>(&mut self, size: u64, values: impl Iterator<Item = &'v [u8]>) -> Result<u64> {
843 debug_assert!(size > 0, "the caller refuses a size of zero");
844 let old_span = self.len();
845 let keep = if old_span == 0 || size == old_span {
851 0
852 } else if size < old_span {
853 size
854 } else if self.insert.is_some() && self.next_cursor() < old_span {
855 old_span
856 } else {
857 0
858 };
859 if keep > 0 {
860 self.rework(old_span, keep)?;
861 }
862
863 let mut cursor = self.insert.unwrap_or(0);
864 for v in values {
865 cursor = self.next_cursor();
866 if cursor >= size {
867 cursor %= size;
868 }
869 self.set(cursor, v)?;
870 self.insert = Some(cursor);
871 }
872 Ok(cursor)
873 }
874
875 const fn next_cursor(&self) -> u64 {
881 match self.insert {
882 None => 0,
883 Some(i) => i.wrapping_add(1),
884 }
885 }
886
887 fn rework(&mut self, old_span: u64, keep: u64) -> Result<()> {
894 let anchor = match self.insert {
895 None => old_span - 1,
896 Some(i) => i % old_span,
897 };
898 let back = |i: u64| if i == 0 { old_span - 1 } else { i - 1 };
899 let forward = |i: u64| if i + 1 == old_span { 0 } else { i + 1 };
900
901 let mut kept = 0;
902 let mut src = anchor;
903 while kept < keep && self.get(src).is_some() {
904 kept += 1;
905 src = back(src);
906 }
907 src = forward(src);
909
910 let mut fresh = Array::new();
911 for dst in 0..kept {
912 let mut buf = [0u8; ELEMENT_MAX];
913 let el = self.get(src).expect("the walk stopped at the first hole");
914 fresh.set(dst, el.text(&mut buf))?;
915 src = forward(src);
916 }
917 fresh.insert = kept.checked_sub(1);
918 *self = fresh;
919 Ok(())
920 }
921
922 pub fn last_items<F>(&self, count: u64, newest_first: bool, mut f: F) -> u64
929 where
930 F: FnMut(Option<Element<'_>>),
931 {
932 let steps = count.min(self.count);
933 if steps == 0 {
934 return 0;
935 }
936 let span = self.len();
937 let anchor = self.insert.unwrap_or(span - 1);
943 let near = steps.min(anchor + 1);
948 let wrapped = steps - near;
949 let near_lo = anchor - (near - 1);
950 let wrapped_lo = span - wrapped;
951
952 let mut emit = |i: u64| f(self.get(i));
953 if newest_first {
954 (near_lo..=anchor).rev().for_each(&mut emit);
955 (wrapped_lo..span).rev().for_each(&mut emit);
956 } else {
957 (wrapped_lo..span).for_each(&mut emit);
958 (near_lo..=anchor).for_each(&mut emit);
959 }
960 steps
961 }
962
963 pub fn scan<F>(&self, start: u64, end: u64, mut f: F)
972 where
973 F: FnMut(u64, Element<'_>) -> bool,
974 {
975 let reverse = start > end;
976 let (lo, hi) = if reverse { (end, start) } else { (start, end) };
977 let (lo_id, lo_off) = split(lo);
978 let (hi_id, hi_off) = split(hi);
979 let first = match self.find(lo_id) {
980 Ok(at) | Err(at) => at,
981 };
982 let last = match self.find(hi_id) {
983 Ok(at) => at + 1,
984 Err(at) => at,
985 };
986
987 let mut visit = |at: usize| {
988 let (id, slice) = &self.slices[at];
989 let from = if *id == lo_id { lo_off } else { 0 };
990 let to = if *id == hi_id {
991 hi_off
992 } else {
993 (SLICE_SIZE - 1) as u16
994 };
995 let base = id * SLICE_SIZE;
996 slice.window(from, to, reverse, &mut |off, w| {
997 let el = self.decode(w).expect("a populated word decodes");
998 f(base + u64::from(off), el)
999 })
1000 };
1001 if reverse {
1002 for at in (first..last).rev() {
1003 if !visit(at) {
1004 return;
1005 }
1006 }
1007 } else {
1008 for at in first..last {
1009 if !visit(at) {
1010 return;
1011 }
1012 }
1013 }
1014 }
1015
1016 #[must_use]
1022 pub fn info(&self, full: bool) -> Info {
1023 let mut info = Info {
1024 count: self.count,
1025 len: self.len(),
1026 next_insert: self.next_index().unwrap_or(0),
1029 slices: self.slices.len() as u64,
1030 directory_size: self.slices.capacity() as u64,
1031 slice_size: SLICE_SIZE,
1032 ..Info::default()
1033 };
1034 if !full {
1035 return info;
1036 }
1037 let (mut window, mut filled, mut room) = (0u64, 0u64, 0u64);
1038 for (_, slice) in &self.slices {
1039 match &slice.layout {
1040 Layout::Dense { words, .. } => {
1041 info.dense_slices += 1;
1042 window += words.len() as u64;
1043 filled += u64::from(slice.count);
1044 }
1045 Layout::Sparse { offs, .. } => {
1046 info.sparse_slices += 1;
1047 room += offs.capacity() as u64;
1048 }
1049 }
1050 }
1051 let ratio = |a: u64, b: u64| if b == 0 { 0.0 } else { a as f64 / b as f64 };
1052 info.avg_dense_size = ratio(window, info.dense_slices);
1053 info.avg_dense_fill = ratio(filled, window);
1054 info.avg_sparse_size = ratio(room, info.sparse_slices);
1055 info
1056 }
1057
1058 #[must_use]
1060 pub fn memory_bytes(&self) -> usize {
1061 self.slices.capacity() * size_of::<(u64, Slice)>()
1062 + self
1063 .slices
1064 .iter()
1065 .map(|(_, s)| s.memory_bytes())
1066 .sum::<usize>()
1067 + self.blob.capacity()
1068 }
1069
1070 pub fn freeze(&self, out: &mut Vec<u8>) {
1087 out.push(match self.insert {
1088 Some(_) => FORM_SLICES | HAS_INSERT,
1089 None => FORM_SLICES,
1090 });
1091 if let Some(at) = self.insert {
1092 frozen::put_uint(out, at);
1093 }
1094 frozen::put_uint(out, self.count);
1095
1096 frozen::put_uint(out, (self.blob.len() - self.dead) as u64);
1099 for (_, slice) in &self.slices {
1100 for w in slice.words() {
1101 if !w.is_empty() && w.tag() == TAG_BLOB {
1102 let (start, len) = w.blob_span();
1103 out.extend_from_slice(&self.blob[start..start + len]);
1104 }
1105 }
1106 }
1107
1108 frozen::put_uint(out, self.slices.len() as u64);
1109 let mut at = 0usize;
1112 for (id, slice) in &self.slices {
1113 frozen::put_uint(out, *id);
1114 match &slice.layout {
1115 Layout::Sparse { offs, words } => {
1116 out.push(LAYOUT_SPARSE);
1117 frozen::put_uint(out, words.len() as u64);
1118 for (&off, &w) in offs.iter().zip(words) {
1119 frozen::put_uint(out, u64::from(off));
1120 frozen::put_uint(out, moved(w, &mut at));
1121 }
1122 }
1123 Layout::Dense { offset, words } => {
1124 out.push(LAYOUT_DENSE);
1125 frozen::put_uint(out, u64::from(*offset));
1126 frozen::put_uint(out, words.len() as u64);
1127 for &w in words {
1128 frozen::put_uint(out, moved(w, &mut at));
1129 }
1130 }
1131 }
1132 }
1133 }
1134
1135 pub fn thaw(bytes: &[u8]) -> core::result::Result<Array, Broken> {
1146 let mut cut = frozen::Cut::new(bytes);
1147 let tag = cut.byte()?;
1148 if tag & !HAS_INSERT != FORM_SLICES {
1149 return Err(Broken::Form);
1150 }
1151 let insert = if tag & HAS_INSERT != 0 {
1152 let at = cut.uint()?;
1153 if at > INDEX_MAX {
1154 return Err(Broken::Body);
1155 }
1156 Some(at)
1157 } else {
1158 None
1159 };
1160 let count = cut.uint()?;
1161 let blob = cut.bytes()?.to_vec();
1162
1163 let n = usize::try_from(cut.uint()?).map_err(|_| Broken::Short)?;
1164 if n > cut.rest().len() {
1167 return Err(Broken::Body);
1168 }
1169 let mut slices: Vec<(u64, Slice)> = Vec::with_capacity(n);
1170 let mut used = 0usize;
1171 let mut seen = 0u64;
1172 for _ in 0..n {
1173 let id = cut.uint()?;
1174 if id > INDEX_MAX >> SLICE_BITS {
1175 return Err(Broken::Body);
1176 }
1177 if slices.last().is_some_and(|(last, _)| id <= *last) {
1178 return Err(Broken::Body);
1179 }
1180 let slice = read_slice(&mut cut, blob.len(), &mut used)?;
1181 seen += u64::from(slice.count);
1182 slices.push((id, slice));
1183 }
1184 if seen != count || used != blob.len() {
1185 return Err(Broken::Body);
1186 }
1187 Ok(Array {
1188 slices,
1189 blob,
1190 dead: 0,
1191 count,
1192 insert,
1193 })
1194 }
1195
1196 fn find(&self, id: u64) -> core::result::Result<usize, usize> {
1198 self.slices.binary_search_by(|(have, _)| {
1199 if *have < id {
1200 Ordering::Less
1201 } else if *have > id {
1202 Ordering::Greater
1203 } else {
1204 Ordering::Equal
1205 }
1206 })
1207 }
1208
1209 fn clear_within(&mut self, at: usize, from: u16, to: u16) -> u64 {
1216 let slice = &mut self.slices[at].1;
1217 let mut gone = 0u64;
1218 let mut dead = 0usize;
1219 match &mut slice.layout {
1220 Layout::Sparse { offs, words } => {
1221 let lo = offs.partition_point(|&o| o < from);
1222 let hi = offs.partition_point(|&o| o <= to);
1223 for w in &words[lo..hi] {
1226 gone += 1;
1227 if w.tag() == TAG_BLOB {
1228 dead += w.blob_span().1;
1229 }
1230 }
1231 offs.drain(lo..hi);
1232 words.drain(lo..hi);
1233 }
1234 Layout::Dense { offset, words } => {
1235 let base = *offset;
1236 let lo = usize::from(from.saturating_sub(base));
1237 if to >= base && lo < words.len() {
1238 let hi = usize::from(to - base).min(words.len() - 1);
1239 for w in &mut words[lo..=hi] {
1240 if !w.is_empty() {
1241 gone += 1;
1242 if w.tag() == TAG_BLOB {
1243 dead += w.blob_span().1;
1244 }
1245 *w = Word::EMPTY;
1246 }
1247 }
1248 }
1249 }
1250 }
1251 slice.count -= gone as u16;
1252 slice.trim();
1253 self.dead += dead;
1254 gone
1255 }
1256
1257 fn retire(&mut self, w: Word) {
1259 if !w.is_empty() && w.tag() == TAG_BLOB {
1260 self.dead += w.blob_span().1;
1261 }
1262 }
1263
1264 fn encode(&mut self, val: &[u8]) -> Result<Word> {
1266 if let Some(i) = num::parse_i64(val)
1267 && (INT_LO..=INT_HI).contains(&i)
1268 {
1269 return Ok(Word::from_int(i));
1270 }
1271 if let Some(w) = float_word(val) {
1272 return Ok(w);
1273 }
1274 if val.len() <= INLINE_MAX {
1275 return Ok(Word::from_short(val));
1276 }
1277 if val.len() > VALUE_MAX {
1278 return Err(Error::new(Code::Full, VALUE_TOO_LONG));
1279 }
1280 if self.blob.len() + val.len() > BLOB_MAX {
1281 self.compact();
1282 }
1283 if self.blob.len() + val.len() > BLOB_MAX {
1284 return Err(Error::new(Code::Full, BLOB_TOO_LONG));
1285 }
1286 let start = self.blob.len();
1287 self.blob.extend_from_slice(val);
1288 Ok(Word::from_blob(start, val.len()))
1289 }
1290
1291 fn decode(&self, w: Word) -> Option<Element<'_>> {
1292 if w.is_empty() {
1293 return None;
1294 }
1295 Some(match w.tag() {
1296 TAG_INT => Element::Int(w.to_int()),
1297 TAG_FLOAT => Element::Float(w.to_float()),
1298 TAG_STR => Element::Short(w.to_short()),
1299 _ => {
1300 let (start, len) = w.blob_span();
1301 Element::Str(&self.blob[start..start + len])
1302 }
1303 })
1304 }
1305
1306 fn compact(&mut self) {
1309 let mut fresh = Vec::with_capacity(self.blob.len() - self.dead);
1310 for (_, slice) in &mut self.slices {
1311 for w in slice.words_mut() {
1312 if w.is_empty() || w.tag() != TAG_BLOB {
1313 continue;
1314 }
1315 let (start, len) = w.blob_span();
1316 let to = fresh.len();
1317 fresh.extend_from_slice(&self.blob[start..start + len]);
1318 *w = Word::from_blob(to, len);
1319 }
1320 }
1321 self.blob = fresh;
1322 self.dead = 0;
1323 }
1324
1325 fn maybe_compact(&mut self) {
1326 if self.dead >= COMPACT_MIN && self.dead * 2 >= self.blob.len() {
1327 self.compact();
1328 }
1329 }
1330
1331 fn maybe_compact_slices(&mut self) {
1337 if self.slices.capacity() > 16 && self.slices.capacity() > self.slices.len() * 4 {
1338 self.slices.shrink_to_fit();
1339 }
1340 }
1341}
1342
1343#[derive(Debug, Default, Clone, Copy)]
1350pub struct Info {
1351 pub count: u64,
1353 pub len: u64,
1355 pub next_insert: u64,
1357 pub slices: u64,
1359 pub directory_size: u64,
1361 pub slice_size: u64,
1363 pub dense_slices: u64,
1365 pub sparse_slices: u64,
1367 pub avg_dense_size: f64,
1369 pub avg_dense_fill: f64,
1371 pub avg_sparse_size: f64,
1373}
1374
1375pub const BLOB_TOO_LONG: &str = "array values exceed the four gigabyte per key limit";
1377
1378pub const VALUE_TOO_LONG: &str = "array value exceeds the one gigabyte limit";
1380
1381pub const INSERT_OVERFLOW: &str = "insert index overflow";
1387
1388fn moved(w: Word, at: &mut usize) -> u64 {
1395 if w.is_empty() || w.tag() != TAG_BLOB {
1396 return w.0;
1397 }
1398 let (_, len) = w.blob_span();
1399 let start = *at;
1400 *at += len;
1401 Word::from_blob(start, len).0
1402}
1403
1404fn read_word(
1410 cut: &mut frozen::Cut<'_>,
1411 blob: usize,
1412 used: &mut usize,
1413) -> core::result::Result<Word, Broken> {
1414 let w = Word(cut.uint()?);
1415 if !w.is_empty() && w.tag() == TAG_BLOB {
1416 let (start, len) = w.blob_span();
1417 if len <= INLINE_MAX || start + len > blob {
1420 return Err(Broken::Body);
1421 }
1422 *used += len;
1423 }
1424 Ok(w)
1425}
1426
1427fn read_slice(
1429 cut: &mut frozen::Cut<'_>,
1430 blob: usize,
1431 used: &mut usize,
1432) -> core::result::Result<Slice, Broken> {
1433 match cut.byte()? {
1434 LAYOUT_SPARSE => {
1435 let n = usize::try_from(cut.uint()?).map_err(|_| Broken::Short)?;
1436 if n == 0 || n > cut.rest().len() {
1439 return Err(Broken::Body);
1440 }
1441 let mut offs: Vec<u16> = Vec::with_capacity(n);
1442 let mut words = Vec::with_capacity(n);
1443 for _ in 0..n {
1444 let off = u16::try_from(cut.uint()?).map_err(|_| Broken::Body)?;
1445 if u64::from(off) >= SLICE_SIZE {
1446 return Err(Broken::Body);
1447 }
1448 if offs.last().is_some_and(|last| off <= *last) {
1449 return Err(Broken::Body);
1450 }
1451 let w = read_word(cut, blob, used)?;
1452 if w.is_empty() {
1455 return Err(Broken::Body);
1456 }
1457 offs.push(off);
1458 words.push(w);
1459 }
1460 Ok(Slice {
1461 count: n as u16,
1462 layout: Layout::Sparse { offs, words },
1463 })
1464 }
1465 LAYOUT_DENSE => {
1466 let offset = u16::try_from(cut.uint()?).map_err(|_| Broken::Body)?;
1467 let n = usize::try_from(cut.uint()?).map_err(|_| Broken::Short)?;
1468 if n == 0 || n > cut.rest().len() {
1469 return Err(Broken::Body);
1470 }
1471 if u64::from(offset) + n as u64 > SLICE_SIZE {
1472 return Err(Broken::Body);
1473 }
1474 let mut words = Vec::with_capacity(n);
1475 let mut live = 0u16;
1476 for _ in 0..n {
1477 let w = read_word(cut, blob, used)?;
1478 if !w.is_empty() {
1479 live += 1;
1480 }
1481 words.push(w);
1482 }
1483 if words[0].is_empty() || words[n - 1].is_empty() {
1486 return Err(Broken::Body);
1487 }
1488 Ok(Slice {
1489 count: live,
1490 layout: Layout::Dense { offset, words },
1491 })
1492 }
1493 _ => Err(Broken::Form),
1494 }
1495}
1496
1497#[inline]
1499const fn split(idx: u64) -> (u64, u16) {
1500 (idx >> SLICE_BITS, (idx & (SLICE_SIZE - 1)) as u16)
1501}
1502
1503fn float_word(val: &[u8]) -> Option<Word> {
1511 let body = match val.first() {
1515 Some(b'-') if val.len() > 1 => &val[1..],
1516 Some(_) => val,
1517 None => return None,
1518 };
1519 let mut dots = 0;
1520 for &c in body {
1521 match c {
1522 b'.' => dots += 1,
1523 b'0'..=b'9' => {}
1524 _ => return None,
1525 }
1526 }
1527 if dots != 1 {
1528 return None;
1529 }
1530
1531 let d = num::parse_f64(val)?;
1532 if !d.is_finite() {
1533 return None;
1534 }
1535 let trunc = f64::from_bits(d.to_bits() & !TAG_MASK);
1541 let mut buf = [0u8; ELEMENT_MAX];
1542 let el = Element::Float(trunc);
1543 if el.text(&mut buf) == val {
1544 Some(Word::from_float_bits(trunc.to_bits()))
1545 } else {
1546 None
1547 }
1548}
1549
1550#[cfg(test)]
1551mod tests {
1552 use super::*;
1553 use crate::many;
1554
1555 fn read(a: &Array, idx: u64) -> Option<Vec<u8>> {
1557 let el = a.get(idx)?;
1558 let mut buf = [0u8; ELEMENT_MAX];
1559 Some(el.text(&mut buf).to_vec())
1560 }
1561
1562 fn set(a: &mut Array, idx: u64, val: &[u8]) -> bool {
1563 a.set(idx, val).expect("a value that fits")
1564 }
1565
1566 fn scan(a: &Array, start: u64, end: u64, limit: usize) -> Vec<(u64, Vec<u8>)> {
1568 let mut got = Vec::new();
1569 a.scan(start, end, |i, el| {
1570 let mut buf = [0u8; ELEMENT_MAX];
1571 got.push((i, el.text(&mut buf).to_vec()));
1572 got.len() < limit
1573 });
1574 got
1575 }
1576
1577 fn last(a: &Array, count: u64, newest_first: bool) -> Vec<Option<Vec<u8>>> {
1579 let mut got = Vec::new();
1580 let n = a.last_items(count, newest_first, |el| {
1581 got.push(el.map(|e| {
1582 let mut buf = [0u8; ELEMENT_MAX];
1583 e.text(&mut buf).to_vec()
1584 }));
1585 });
1586 assert_eq!(n as usize, got.len(), "the count is what it emitted");
1587 got
1588 }
1589
1590 fn append(a: &mut Array, vals: &[&[u8]]) -> Result<u64> {
1591 a.append(vals.iter().copied())
1592 }
1593
1594 fn ring(a: &mut Array, size: u64, vals: &[&[u8]]) -> u64 {
1595 a.ring(size, vals.iter().copied()).expect("values that fit")
1596 }
1597
1598 #[test]
1599 fn a_value_comes_back_the_way_it_went_in() {
1600 let mut a = Array::new();
1601 assert!(set(&mut a, 0, b"hello"));
1602 assert!(set(&mut a, 1, b"a much longer value than fits in a word"));
1603 assert!(set(&mut a, 2, b"42"));
1604 assert!(set(&mut a, 3, b"1.5"));
1605 assert!(set(&mut a, 4, b""));
1606
1607 assert_eq!(read(&a, 0).as_deref(), Some(&b"hello"[..]));
1608 assert_eq!(
1609 read(&a, 1).as_deref(),
1610 Some(&b"a much longer value than fits in a word"[..])
1611 );
1612 assert_eq!(read(&a, 2).as_deref(), Some(&b"42"[..]));
1613 assert_eq!(read(&a, 3).as_deref(), Some(&b"1.5"[..]));
1614 assert_eq!(read(&a, 4).as_deref(), Some(&b""[..]));
1615 assert_eq!(read(&a, 5), None);
1616 }
1617
1618 #[test]
1621 fn the_length_is_the_high_water_mark_and_the_count_is_the_population() {
1622 let mut a = Array::new();
1623 assert_eq!(a.len(), 0);
1624 assert_eq!(a.count(), 0);
1625 assert!(a.is_empty());
1626
1627 set(&mut a, 1_000_000, b"x");
1628 assert_eq!(a.len(), 1_000_001);
1629 assert_eq!(a.count(), 1);
1630 assert!(!a.is_empty());
1631
1632 set(&mut a, 5, b"y");
1633 assert_eq!(a.len(), 1_000_001, "a lower index does not move the length");
1634 assert_eq!(a.count(), 2);
1635
1636 a.del(1_000_000);
1637 assert_eq!(a.len(), 6, "and the length comes back down when it goes");
1638 assert_eq!(a.count(), 1);
1639 }
1640
1641 #[test]
1643 fn an_overwrite_does_not_count_as_a_fill() {
1644 let mut a = Array::new();
1645 assert!(set(&mut a, 7, b"first"));
1646 assert!(!set(&mut a, 7, b"second"));
1647 assert_eq!(a.count(), 1);
1648 assert_eq!(read(&a, 7).as_deref(), Some(&b"second"[..]));
1649 }
1650
1651 #[test]
1652 fn deleting_the_last_element_leaves_nothing_behind() {
1653 let mut a = Array::new();
1654 set(&mut a, 3, b"x");
1655 assert!(a.del(3));
1656 assert!(!a.del(3), "and a second delete finds nothing");
1657 assert!(a.is_empty());
1658 assert_eq!(a.len(), 0);
1659 assert!(a.slices.is_empty(), "the slice went with the last element");
1660 }
1661
1662 #[test]
1664 fn the_index_space_runs_to_the_top() {
1665 let mut a = Array::new();
1666 set(&mut a, 0, b"low");
1667 set(&mut a, INDEX_MAX, b"high");
1668 assert_eq!(read(&a, INDEX_MAX).as_deref(), Some(&b"high"[..]));
1669 assert_eq!(a.count(), 2);
1670 assert_eq!(a.len(), u64::MAX, "the highest index plus one");
1671 assert_eq!(a.slices.len(), 2);
1673 }
1674
1675 #[test]
1678 fn a_slice_changes_layout_when_the_shape_of_it_changes() {
1679 let mut a = Array::new();
1680 for i in 0..SPARSE_MAX as u64 {
1681 set(&mut a, i, b"x");
1682 }
1683 assert!(
1684 matches!(a.slices[0].1.layout, Layout::Sparse { .. }),
1685 "ten scattered elements do not want an index"
1686 );
1687
1688 set(&mut a, 10, b"x");
1689 assert!(
1690 matches!(a.slices[0].1.layout, Layout::Dense { .. }),
1691 "eleven consecutive ones do"
1692 );
1693
1694 for i in 0..8 {
1696 a.del(i);
1697 }
1698 assert!(
1699 matches!(a.slices[0].1.layout, Layout::Sparse { .. }),
1700 "three left is under the floor"
1701 );
1702 assert_eq!(a.count(), 3);
1703 assert_eq!(read(&a, 10).as_deref(), Some(&b"x"[..]));
1704 }
1705
1706 #[test]
1709 fn a_wide_slice_stays_sparse_however_many_elements_it_has() {
1710 let mut a = Array::new();
1711 for i in 0..40 {
1712 set(&mut a, i * 100, b"x");
1713 }
1714 assert!(
1715 matches!(a.slices[0].1.layout, Layout::Sparse { .. }),
1716 "forty elements over four thousand positions is not a window"
1717 );
1718 for i in 0..40 {
1719 assert_eq!(read(&a, i * 100).as_deref(), Some(&b"x"[..]), "at {i}");
1720 }
1721 }
1722
1723 #[test]
1725 fn a_dense_window_grows_downwards_too() {
1726 let mut a = Array::new();
1727 for i in (0..20u64).rev() {
1728 set(&mut a, i, b"v");
1729 }
1730 assert!(matches!(a.slices[0].1.layout, Layout::Dense { .. }));
1731 for i in 0..20 {
1732 assert_eq!(read(&a, i).as_deref(), Some(&b"v"[..]), "at {i}");
1733 }
1734 assert_eq!(a.count(), 20);
1735 assert_eq!(a.len(), 20);
1736 }
1737
1738 #[test]
1739 fn a_range_delete_costs_what_it_touches_and_not_what_it_spans() {
1740 let mut a = Array::new();
1741 set(&mut a, 1, b"a");
1742 set(&mut a, 500_000, b"b");
1743 set(&mut a, INDEX_MAX, b"c");
1744
1745 assert_eq!(a.delete_range(0, INDEX_MAX), 3);
1747 assert!(a.is_empty());
1748 assert!(a.slices.is_empty());
1749 assert_eq!(a.delete_range(0, INDEX_MAX), 0, "and again finds nothing");
1750 }
1751
1752 #[test]
1753 fn a_range_delete_takes_the_ends_and_leaves_the_rest() {
1754 let n = many(30_000u64);
1757 let mut a = Array::new();
1758 for i in 0..n {
1759 set(&mut a, i, b"x");
1760 }
1761 assert_eq!(a.delete_range(100, n - 101), n - 200);
1762 assert_eq!(a.count(), 200);
1763 assert_eq!(read(&a, 99).as_deref(), Some(&b"x"[..]));
1764 assert_eq!(read(&a, 100), None);
1765 assert_eq!(read(&a, n - 101), None);
1766 assert_eq!(read(&a, n - 100).as_deref(), Some(&b"x"[..]));
1767 assert_eq!(a.len(), n);
1768 }
1769
1770 #[test]
1771 fn a_backwards_range_deletes_nothing() {
1772 let mut a = Array::new();
1773 set(&mut a, 5, b"x");
1774 assert_eq!(a.delete_range(9, 4), 0);
1775 assert_eq!(a.count(), 1);
1776 }
1777
1778 #[test]
1785 fn only_a_value_that_prints_back_the_same_becomes_a_number() {
1786 let cases: &[(&[u8], bool)] = &[
1787 (b"0", true),
1788 (b"42", true),
1789 (b"-42", true),
1790 (b"9007199254740993", true),
1791 (b"007", false),
1792 (b"+7", false),
1793 (b"-0", false),
1794 (b" 7", false),
1795 (b"7 ", false),
1796 (b"", false),
1797 ];
1798 for &(val, want) in cases {
1799 let mut a = Array::new();
1800 set(&mut a, 0, val);
1801 let is_int = matches!(a.get(0), Some(Element::Int(_)));
1802 assert_eq!(is_int, want, "{}", String::from_utf8_lossy(val));
1803 assert_eq!(read(&a, 0).as_deref(), Some(val), "round trip");
1804 }
1805 }
1806
1807 #[test]
1809 fn only_a_double_that_prints_back_the_same_is_stored_as_one() {
1810 let cases: &[(&[u8], bool)] = &[
1811 (b"1.0", true),
1812 (b"1.5", true),
1813 (b"-2.25", true),
1814 (b"0.0", true),
1815 (b"3.14", false),
1818 (b"1.10", false),
1819 (b"-0.0", true),
1822 (b"1.", false),
1823 (b".5", false),
1824 (b"1e5", false),
1825 (b"nan", false),
1826 (b"inf", false),
1827 ];
1828 for &(val, want) in cases {
1829 let mut a = Array::new();
1830 set(&mut a, 0, val);
1831 let is_float = matches!(a.get(0), Some(Element::Float(_)));
1832 assert_eq!(is_float, want, "{}", String::from_utf8_lossy(val));
1833 assert_eq!(read(&a, 0).as_deref(), Some(val), "round trip");
1834 }
1835 }
1836
1837 #[test]
1840 fn the_blob_is_compacted_once_enough_of_it_is_dead() {
1841 let mut a = Array::new();
1842 let long = vec![b'a'; 64];
1843 for i in 0..1000 {
1844 set(&mut a, i, &long);
1845 }
1846 let full = a.blob.len();
1847 assert_eq!(full, 64_000);
1848
1849 for i in 0..1000 {
1851 set(&mut a, i, b"short");
1852 }
1853 assert!(a.blob.len() < full / 2, "{} bytes left", a.blob.len());
1854 assert_eq!(a.count(), 1000);
1855 for i in 0..1000 {
1856 assert_eq!(read(&a, i).as_deref(), Some(&b"short"[..]), "at {i}");
1857 }
1858 }
1859
1860 #[test]
1863 fn compaction_keeps_the_values_that_survive_it() {
1864 let n = many(2000u64);
1865 let mut a = Array::new();
1866 for i in 0..n {
1867 let val = format!("value number {i} padded out past the inline limit");
1868 set(&mut a, i, val.as_bytes());
1869 }
1870 for i in (0..n).step_by(2) {
1875 a.del(i);
1876 }
1877 assert!(a.dead * 2 < a.blob.len(), "the blob was rewritten");
1878 for i in (1..n).step_by(2) {
1879 let want = format!("value number {i} padded out past the inline limit");
1880 assert_eq!(read(&a, i).as_deref(), Some(want.as_bytes()), "at {i}");
1881 }
1882 }
1883
1884 #[test]
1885 fn a_value_over_the_ceiling_is_an_error_and_not_a_panic() {
1886 let mut a = Array::new();
1887 let huge = vec![b'x'; VALUE_MAX + 1];
1888 let e = a.set(0, &huge).unwrap_err();
1889 assert_eq!(e.code(), Code::Full);
1890 assert_eq!(e.message(), VALUE_TOO_LONG);
1891 assert!(a.is_empty(), "and nothing was written");
1892 }
1893
1894 #[test]
1896 fn a_word_holds_what_it_was_given() {
1897 assert!(Word::EMPTY.is_empty());
1898 for i in [0i64, 1, -1, INT_LO, INT_HI, 12345, -99999] {
1899 let w = Word::from_int(i);
1900 assert!(!w.is_empty());
1901 assert_eq!(w.tag(), TAG_INT);
1902 assert_eq!(w.to_int(), i, "{i}");
1903 }
1904 for d in [0.0f64, 1.5, -2.25, 1e300] {
1905 let bits = d.to_bits() & !TAG_MASK;
1906 let w = Word::from_float_bits(bits);
1907 assert!(!w.is_empty());
1908 assert_eq!(w.tag(), TAG_FLOAT);
1909 assert_eq!(w.to_float().to_bits(), bits);
1910 }
1911 for s in [&b""[..], b"a", b"abc", b"1234567"] {
1912 let w = Word::from_short(s);
1913 assert!(!w.is_empty(), "{s:?}");
1914 assert_eq!(w.tag(), TAG_STR);
1915 assert_eq!(w.to_short().as_bytes(), s);
1916 }
1917 let w = Word::from_blob(4_000_000_000, 1_000_000);
1918 assert_eq!(w.tag(), TAG_BLOB);
1919 assert_eq!(w.blob_span(), (4_000_000_000, 1_000_000));
1920 assert!(!w.is_empty());
1921 }
1922
1923 #[test]
1924 fn what_it_holds_is_what_it_says_it_holds() {
1925 let mut a = Array::new();
1926 assert_eq!(a.memory_bytes(), 0);
1927 for i in 0..1000u64 {
1928 set(&mut a, i * 7, b"a value past the inline limit");
1929 }
1930 let held = a.memory_bytes();
1931 assert!(held > 29_000, "{held} bytes for 29 kilobytes of values");
1932 a.delete_range(0, u64::MAX - 1);
1933 assert!(
1934 a.memory_bytes() < held / 2,
1935 "{} bytes left of {held}",
1936 a.memory_bytes()
1937 );
1938 }
1939
1940 #[test]
1943 fn it_agrees_with_a_map_over_a_scramble_of_writes() {
1944 use std::collections::BTreeMap;
1945
1946 let mut a = Array::new();
1947 let mut want: BTreeMap<u64, Vec<u8>> = BTreeMap::new();
1948 let mut seed = 0x9e37_79b9_7f4a_7c15u64;
1949 let mut next = || {
1950 seed ^= seed << 13;
1951 seed ^= seed >> 7;
1952 seed ^= seed << 17;
1953 seed
1954 };
1955
1956 let steps = many(20_000u64);
1962 let width = many(500u64);
1963 for step in 0..steps {
1964 let idx = next() % steps;
1965 match step % 5 {
1966 0..=2 => {
1967 let val = format!("v{step}");
1968 let was_new = set(&mut a, idx, val.as_bytes());
1969 assert_eq!(was_new, want.insert(idx, val.into_bytes()).is_none());
1970 }
1971 3 => {
1972 assert_eq!(a.del(idx), want.remove(&idx).is_some());
1973 }
1974 _ => {
1975 let hi = idx + (next() % width);
1976 let gone = a.delete_range(idx, hi);
1977 let keys: Vec<u64> = want.range(idx..=hi).map(|(k, _)| *k).collect();
1978 assert_eq!(gone, keys.len() as u64);
1979 for k in keys {
1980 want.remove(&k);
1981 }
1982 }
1983 }
1984 assert_eq!(a.count(), want.len() as u64, "count after step {step}");
1985 }
1986
1987 assert_eq!(
1988 a.len(),
1989 want.keys().next_back().map_or(0, |k| k + 1),
1990 "the high water mark"
1991 );
1992 for (&idx, val) in &want {
1993 assert_eq!(read(&a, idx).as_deref(), Some(&val[..]), "at {idx}");
1994 }
1995 }
1996
1997 #[test]
1998 fn a_scan_finds_the_elements_and_steps_over_the_holes() {
1999 let mut a = Array::new();
2000 set(&mut a, 0, b"a");
2001 set(&mut a, 5, b"b");
2002 set(&mut a, SLICE_SIZE * 2 + 7, b"c");
2004
2005 let all = vec![
2006 (0, b"a".to_vec()),
2007 (5, b"b".to_vec()),
2008 (SLICE_SIZE * 2 + 7, b"c".to_vec()),
2009 ];
2010 assert_eq!(scan(&a, 0, INDEX_MAX, usize::MAX), all);
2013 let mut backwards = all.clone();
2014 backwards.reverse();
2015 assert_eq!(scan(&a, INDEX_MAX, 0, usize::MAX), backwards);
2016
2017 assert_eq!(scan(&a, 1, 5, usize::MAX), all[1..2].to_vec());
2020 assert_eq!(scan(&a, 6, SLICE_SIZE, usize::MAX), Vec::new());
2021 assert_eq!(scan(&a, 0, INDEX_MAX, 2), all[..2].to_vec());
2022 assert_eq!(scan(&Array::new(), 0, INDEX_MAX, usize::MAX), Vec::new());
2023 }
2024
2025 #[test]
2028 fn a_scan_reads_both_layouts_the_same_way() {
2029 let mut a = Array::new();
2030 for i in 0..40u64 {
2031 set(&mut a, i, format!("v{i}").as_bytes());
2032 }
2033 for i in (0..40u64).step_by(2) {
2034 a.del(i);
2035 }
2036 let odd: Vec<(u64, Vec<u8>)> = (1..40u64)
2037 .step_by(2)
2038 .map(|i| (i, format!("v{i}").into_bytes()))
2039 .collect();
2040 assert_eq!(scan(&a, 0, 100, usize::MAX), odd);
2041
2042 let mut b = Array::new();
2045 for i in (1..40u64).step_by(2) {
2046 set(&mut b, i, format!("v{i}").as_bytes());
2047 }
2048 assert_eq!(scan(&b, 0, 100, usize::MAX), odd);
2049 }
2050
2051 #[test]
2052 fn the_cursor_moves_only_when_something_appends_to_it() {
2053 let mut a = Array::new();
2054 assert_eq!(a.next_index(), Some(0));
2055 set(&mut a, 0, b"set");
2058 assert_eq!(a.next_index(), Some(0));
2059 assert_eq!(append(&mut a, &[b"x", b"y"]).expect("room"), 1);
2060 assert_eq!(read(&a, 0).as_deref(), Some(&b"x"[..]));
2061 assert_eq!(a.next_index(), Some(2));
2062
2063 a.seek(100);
2065 assert_eq!(a.next_index(), Some(100));
2066 assert_eq!(append(&mut a, &[b"z"]).expect("room"), 100);
2067 assert_eq!(read(&a, 100).as_deref(), Some(&b"z"[..]));
2068 a.seek(0);
2069 assert_eq!(a.next_index(), Some(0));
2070 }
2071
2072 #[test]
2073 fn an_append_that_would_run_off_the_top_writes_nothing() {
2074 let mut a = Array::new();
2075 a.seek(INDEX_MAX - 1);
2076 let e = append(&mut a, &[b"x", b"y", b"z"]).unwrap_err();
2077 assert_eq!(e.code(), Code::Invalid);
2078 assert_eq!(e.message(), INSERT_OVERFLOW);
2079 assert_eq!(a.count(), 0, "and none of the batch landed");
2080
2081 assert_eq!(append(&mut a, &[b"x", b"y"]).expect("room"), INDEX_MAX);
2083 assert_eq!(a.next_index(), None);
2084 assert_eq!(
2085 append(&mut a, &[b"z"]).unwrap_err().message(),
2086 INSERT_OVERFLOW
2087 );
2088 }
2089
2090 #[test]
2091 fn a_ring_wraps_round_at_its_size() {
2092 let mut a = Array::new();
2093 assert_eq!(ring(&mut a, 3, &[b"a", b"b", b"c"]), 2);
2094 assert_eq!(ring(&mut a, 3, &[b"d", b"e"]), 1);
2095 assert_eq!(a.len(), 3, "it never grows past the size it was given");
2096 assert_eq!(a.count(), 3);
2097 assert_eq!(read(&a, 0).as_deref(), Some(&b"d"[..]));
2098 assert_eq!(read(&a, 1).as_deref(), Some(&b"e"[..]));
2099 assert_eq!(read(&a, 2).as_deref(), Some(&b"c"[..]));
2100 }
2101
2102 #[test]
2106 fn a_ring_that_changes_size_is_renumbered_oldest_first() {
2107 let mut a = Array::new();
2108 ring(&mut a, 3, &[b"a", b"b", b"c", b"d", b"e"]);
2109 assert_eq!(ring(&mut a, 5, &[b"f"]), 3);
2111 assert_eq!(
2112 (0..4).map(|i| read(&a, i)).collect::<Vec<_>>(),
2113 vec![
2114 Some(b"c".to_vec()),
2115 Some(b"d".to_vec()),
2116 Some(b"e".to_vec()),
2117 Some(b"f".to_vec())
2118 ]
2119 );
2120
2121 let mut b = Array::new();
2123 ring(&mut b, 3, &[b"a", b"b", b"c", b"d", b"e"]);
2124 assert_eq!(ring(&mut b, 2, &[b"f"]), 0);
2125 assert_eq!(b.count(), 2);
2126 assert_eq!(read(&b, 0).as_deref(), Some(&b"f"[..]));
2127 assert_eq!(read(&b, 1).as_deref(), Some(&b"e"[..]));
2128 }
2129
2130 #[test]
2133 fn a_hole_cuts_what_a_resize_keeps() {
2134 let mut a = Array::new();
2135 ring(&mut a, 4, &[b"a", b"b", b"c", b"d", b"e"]);
2136 a.del(2);
2138 assert_eq!(ring(&mut a, 8, &[b"f"]), 2);
2139 assert_eq!(
2142 (0..3).map(|i| read(&a, i)).collect::<Vec<_>>(),
2143 vec![
2144 Some(b"d".to_vec()),
2145 Some(b"e".to_vec()),
2146 Some(b"f".to_vec())
2147 ]
2148 );
2149 }
2150
2151 #[test]
2152 fn the_last_items_walk_wraps_and_reports_the_holes() {
2153 let mut a = Array::new();
2154 ring(&mut a, 4, &[b"a", b"b", b"c", b"d", b"e"]);
2155 assert_eq!(
2158 last(&a, 3, false),
2159 vec![
2160 Some(b"c".to_vec()),
2161 Some(b"d".to_vec()),
2162 Some(b"e".to_vec())
2163 ]
2164 );
2165 assert_eq!(
2166 last(&a, 3, true),
2167 vec![
2168 Some(b"e".to_vec()),
2169 Some(b"d".to_vec()),
2170 Some(b"c".to_vec())
2171 ]
2172 );
2173 assert_eq!(last(&a, 99, false).len(), 4);
2175 assert_eq!(last(&a, 0, false), Vec::new());
2176 assert_eq!(last(&Array::new(), 5, false), Vec::new());
2177
2178 let mut b = Array::new();
2181 set(&mut b, 0, b"a");
2182 set(&mut b, 2, b"c");
2183 assert_eq!(last(&b, 5, false), vec![None, Some(b"c".to_vec())]);
2184 }
2185
2186 #[test]
2189 fn a_copy_of_an_array_remembers_the_cursor() {
2190 let mut a = Array::new();
2191 append(&mut a, &[b"x", b"y"]).expect("room");
2192 let mut b = a.clone();
2193 assert_eq!(b.next_index(), Some(2));
2194 assert_eq!(append(&mut b, &[b"z"]).expect("room"), 2);
2195 assert_eq!(a.next_index(), Some(2), "and the two do not share it");
2196 }
2197
2198 fn round_trip(a: &Array) -> Array {
2200 let mut buf = Vec::new();
2201 a.freeze(&mut buf);
2202 let back = Array::thaw(&buf).expect("what freeze wrote");
2203 assert_eq!(back.count(), a.count(), "the population");
2204 assert_eq!(back.len(), a.len(), "the high water mark");
2205 assert_eq!(back.next_index(), a.next_index(), "the insert cursor");
2206 assert_eq!(back.slices.len(), a.slices.len(), "the slice count");
2207 for ((id, was), (back_id, now)) in a.slices.iter().zip(&back.slices) {
2208 assert_eq!(id, back_id, "the slice ids");
2209 assert_eq!(was.count, now.count, "slice {id} holds the same number");
2210 assert_eq!(
2211 matches!(was.layout, Layout::Dense { .. }),
2212 matches!(now.layout, Layout::Dense { .. }),
2213 "slice {id} came back in the layout it left in"
2214 );
2215 }
2216 assert_eq!(
2217 scan(&back, 0, u64::MAX, usize::MAX),
2218 scan(a, 0, u64::MAX, usize::MAX)
2219 );
2220 back
2221 }
2222
2223 #[test]
2224 fn a_frozen_array_comes_back_with_every_value_it_held() {
2225 let mut a = Array::new();
2226 set(&mut a, 0, b"12345");
2229 set(&mut a, 1, b"1.5");
2230 set(&mut a, 2, b"short");
2231 set(
2232 &mut a,
2233 3,
2234 b"a value well past the seven bytes a word can inline",
2235 );
2236 set(&mut a, 9_000_000_000_000, b"a long way up the index space");
2237 let back = round_trip(&a);
2238 assert_eq!(read(&back, 0).as_deref(), Some(&b"12345"[..]));
2239 assert_eq!(read(&back, 1).as_deref(), Some(&b"1.5"[..]));
2240 assert_eq!(read(&back, 2).as_deref(), Some(&b"short"[..]));
2241 assert_eq!(
2242 read(&back, 3).as_deref(),
2243 Some(&b"a value well past the seven bytes a word can inline"[..])
2244 );
2245 assert_eq!(
2246 read(&back, 9_000_000_000_000).as_deref(),
2247 Some(&b"a long way up the index space"[..])
2248 );
2249 assert_eq!(read(&back, 4), None, "and a hole is still a hole");
2250 assert_eq!(back.get(0), Some(Element::Int(12345)), "still an integer");
2251 assert_eq!(back.get(1), Some(Element::Float(1.5)), "still a double");
2252
2253 round_trip(&Array::new());
2254 }
2255
2256 #[test]
2257 fn both_layouts_come_back_in_the_layout_they_left_in() {
2258 let mut dense = Array::new();
2260 for i in 0..=SPARSE_MAX as u64 {
2261 set(&mut dense, i, b"x");
2262 }
2263 assert!(matches!(dense.slices[0].1.layout, Layout::Dense { .. }));
2264 round_trip(&dense);
2265
2266 let mut holed = dense.clone();
2269 for i in 2..5 {
2270 holed.del(i);
2271 }
2272 assert!(matches!(holed.slices[0].1.layout, Layout::Dense { .. }));
2273 assert_eq!(holed.count(), 8);
2274 let back = round_trip(&holed);
2275 assert_eq!(read(&back, 1).as_deref(), Some(&b"x"[..]));
2276 assert_eq!(read(&back, 4), None);
2277
2278 let mut sparse = Array::new();
2280 for i in 0..40 {
2281 set(&mut sparse, i * 100, b"x");
2282 }
2283 assert!(matches!(sparse.slices[0].1.layout, Layout::Sparse { .. }));
2284 round_trip(&sparse);
2285 }
2286
2287 #[test]
2288 fn freezing_an_array_leaves_the_dead_blob_bytes_behind() {
2289 let mut a = Array::new();
2290 let long = vec![b'v'; 200];
2291 for _ in 0..8 {
2294 set(&mut a, 0, &long);
2295 }
2296 assert!(a.dead > 0, "there is dead space to leave behind");
2297 let mut buf = Vec::new();
2298 a.freeze(&mut buf);
2299 let back = Array::thaw(&buf).expect("what freeze wrote");
2300 assert_eq!(back.dead, 0, "a demotion is a compaction");
2301 assert_eq!(back.blob.len(), a.blob.len() - a.dead);
2302 assert_eq!(read(&back, 0).as_deref(), Some(&long[..]));
2303 assert!(
2304 buf.len() < a.blob.len(),
2305 "and the dead bytes never went out"
2306 );
2307 }
2308
2309 #[test]
2310 fn a_frozen_array_keeps_the_insert_cursor() {
2311 let mut a = Array::new();
2312 append(&mut a, &[b"x", b"y", b"z"]).expect("room");
2313 let mut back = round_trip(&a);
2314 assert_eq!(back.next_index(), Some(3));
2315 assert_eq!(append(&mut back, &[b"w"]).expect("room"), 3);
2316
2317 let mut untouched = Array::new();
2320 set(&mut untouched, 99, b"x");
2321 let mut back = round_trip(&untouched);
2322 assert_eq!(back.next_index(), Some(0), "a cursor nothing has moved");
2323 assert_eq!(append(&mut back, &[b"first"]).expect("room"), 0);
2324 }
2325
2326 #[test]
2327 fn a_frozen_array_that_arrives_damaged_is_an_error_and_not_a_panic() {
2328 let mut a = Array::new();
2332 for i in 0..many(200u64) {
2333 set(
2334 &mut a,
2335 i * 7,
2336 format!("value:{i:04} and enough bytes to reach the blob").as_bytes(),
2337 );
2338 }
2339 let mut buf = Vec::new();
2340 a.freeze(&mut buf);
2341 assert!(Array::thaw(&buf).is_ok(), "the body it wrote reads back");
2342
2343 assert!(Array::thaw(&[]).is_err(), "nothing at all");
2344 assert!(Array::thaw(&[99]).is_err(), "a form nobody wrote");
2345 for cut in 1..buf.len().min(96) {
2346 assert!(Array::thaw(&buf[..cut]).is_err(), "cut at {cut}");
2347 }
2348 for at in 0..buf.len().min(96) {
2351 for bit in 0..8 {
2352 let mut bad = buf.clone();
2353 bad[at] ^= 1 << bit;
2354 let _ = Array::thaw(&bad);
2357 }
2358 }
2359 }
2360}