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
1554 fn read(a: &Array, idx: u64) -> Option<Vec<u8>> {
1556 let el = a.get(idx)?;
1557 let mut buf = [0u8; ELEMENT_MAX];
1558 Some(el.text(&mut buf).to_vec())
1559 }
1560
1561 fn set(a: &mut Array, idx: u64, val: &[u8]) -> bool {
1562 a.set(idx, val).expect("a value that fits")
1563 }
1564
1565 fn scan(a: &Array, start: u64, end: u64, limit: usize) -> Vec<(u64, Vec<u8>)> {
1567 let mut got = Vec::new();
1568 a.scan(start, end, |i, el| {
1569 let mut buf = [0u8; ELEMENT_MAX];
1570 got.push((i, el.text(&mut buf).to_vec()));
1571 got.len() < limit
1572 });
1573 got
1574 }
1575
1576 fn last(a: &Array, count: u64, newest_first: bool) -> Vec<Option<Vec<u8>>> {
1578 let mut got = Vec::new();
1579 let n = a.last_items(count, newest_first, |el| {
1580 got.push(el.map(|e| {
1581 let mut buf = [0u8; ELEMENT_MAX];
1582 e.text(&mut buf).to_vec()
1583 }));
1584 });
1585 assert_eq!(n as usize, got.len(), "the count is what it emitted");
1586 got
1587 }
1588
1589 fn append(a: &mut Array, vals: &[&[u8]]) -> Result<u64> {
1590 a.append(vals.iter().copied())
1591 }
1592
1593 fn ring(a: &mut Array, size: u64, vals: &[&[u8]]) -> u64 {
1594 a.ring(size, vals.iter().copied()).expect("values that fit")
1595 }
1596
1597 #[test]
1598 fn a_value_comes_back_the_way_it_went_in() {
1599 let mut a = Array::new();
1600 assert!(set(&mut a, 0, b"hello"));
1601 assert!(set(&mut a, 1, b"a much longer value than fits in a word"));
1602 assert!(set(&mut a, 2, b"42"));
1603 assert!(set(&mut a, 3, b"1.5"));
1604 assert!(set(&mut a, 4, b""));
1605
1606 assert_eq!(read(&a, 0).as_deref(), Some(&b"hello"[..]));
1607 assert_eq!(
1608 read(&a, 1).as_deref(),
1609 Some(&b"a much longer value than fits in a word"[..])
1610 );
1611 assert_eq!(read(&a, 2).as_deref(), Some(&b"42"[..]));
1612 assert_eq!(read(&a, 3).as_deref(), Some(&b"1.5"[..]));
1613 assert_eq!(read(&a, 4).as_deref(), Some(&b""[..]));
1614 assert_eq!(read(&a, 5), None);
1615 }
1616
1617 #[test]
1620 fn the_length_is_the_high_water_mark_and_the_count_is_the_population() {
1621 let mut a = Array::new();
1622 assert_eq!(a.len(), 0);
1623 assert_eq!(a.count(), 0);
1624 assert!(a.is_empty());
1625
1626 set(&mut a, 1_000_000, b"x");
1627 assert_eq!(a.len(), 1_000_001);
1628 assert_eq!(a.count(), 1);
1629 assert!(!a.is_empty());
1630
1631 set(&mut a, 5, b"y");
1632 assert_eq!(a.len(), 1_000_001, "a lower index does not move the length");
1633 assert_eq!(a.count(), 2);
1634
1635 a.del(1_000_000);
1636 assert_eq!(a.len(), 6, "and the length comes back down when it goes");
1637 assert_eq!(a.count(), 1);
1638 }
1639
1640 #[test]
1642 fn an_overwrite_does_not_count_as_a_fill() {
1643 let mut a = Array::new();
1644 assert!(set(&mut a, 7, b"first"));
1645 assert!(!set(&mut a, 7, b"second"));
1646 assert_eq!(a.count(), 1);
1647 assert_eq!(read(&a, 7).as_deref(), Some(&b"second"[..]));
1648 }
1649
1650 #[test]
1651 fn deleting_the_last_element_leaves_nothing_behind() {
1652 let mut a = Array::new();
1653 set(&mut a, 3, b"x");
1654 assert!(a.del(3));
1655 assert!(!a.del(3), "and a second delete finds nothing");
1656 assert!(a.is_empty());
1657 assert_eq!(a.len(), 0);
1658 assert!(a.slices.is_empty(), "the slice went with the last element");
1659 }
1660
1661 #[test]
1663 fn the_index_space_runs_to_the_top() {
1664 let mut a = Array::new();
1665 set(&mut a, 0, b"low");
1666 set(&mut a, INDEX_MAX, b"high");
1667 assert_eq!(read(&a, INDEX_MAX).as_deref(), Some(&b"high"[..]));
1668 assert_eq!(a.count(), 2);
1669 assert_eq!(a.len(), u64::MAX, "the highest index plus one");
1670 assert_eq!(a.slices.len(), 2);
1672 }
1673
1674 #[test]
1677 fn a_slice_changes_layout_when_the_shape_of_it_changes() {
1678 let mut a = Array::new();
1679 for i in 0..SPARSE_MAX as u64 {
1680 set(&mut a, i, b"x");
1681 }
1682 assert!(
1683 matches!(a.slices[0].1.layout, Layout::Sparse { .. }),
1684 "ten scattered elements do not want an index"
1685 );
1686
1687 set(&mut a, 10, b"x");
1688 assert!(
1689 matches!(a.slices[0].1.layout, Layout::Dense { .. }),
1690 "eleven consecutive ones do"
1691 );
1692
1693 for i in 0..8 {
1695 a.del(i);
1696 }
1697 assert!(
1698 matches!(a.slices[0].1.layout, Layout::Sparse { .. }),
1699 "three left is under the floor"
1700 );
1701 assert_eq!(a.count(), 3);
1702 assert_eq!(read(&a, 10).as_deref(), Some(&b"x"[..]));
1703 }
1704
1705 #[test]
1708 fn a_wide_slice_stays_sparse_however_many_elements_it_has() {
1709 let mut a = Array::new();
1710 for i in 0..40 {
1711 set(&mut a, i * 100, b"x");
1712 }
1713 assert!(
1714 matches!(a.slices[0].1.layout, Layout::Sparse { .. }),
1715 "forty elements over four thousand positions is not a window"
1716 );
1717 for i in 0..40 {
1718 assert_eq!(read(&a, i * 100).as_deref(), Some(&b"x"[..]), "at {i}");
1719 }
1720 }
1721
1722 #[test]
1724 fn a_dense_window_grows_downwards_too() {
1725 let mut a = Array::new();
1726 for i in (0..20u64).rev() {
1727 set(&mut a, i, b"v");
1728 }
1729 assert!(matches!(a.slices[0].1.layout, Layout::Dense { .. }));
1730 for i in 0..20 {
1731 assert_eq!(read(&a, i).as_deref(), Some(&b"v"[..]), "at {i}");
1732 }
1733 assert_eq!(a.count(), 20);
1734 assert_eq!(a.len(), 20);
1735 }
1736
1737 #[test]
1738 fn a_range_delete_costs_what_it_touches_and_not_what_it_spans() {
1739 let mut a = Array::new();
1740 set(&mut a, 1, b"a");
1741 set(&mut a, 500_000, b"b");
1742 set(&mut a, INDEX_MAX, b"c");
1743
1744 assert_eq!(a.delete_range(0, INDEX_MAX), 3);
1746 assert!(a.is_empty());
1747 assert!(a.slices.is_empty());
1748 assert_eq!(a.delete_range(0, INDEX_MAX), 0, "and again finds nothing");
1749 }
1750
1751 #[test]
1752 fn a_range_delete_takes_the_ends_and_leaves_the_rest() {
1753 let mut a = Array::new();
1754 for i in 0..30_000u64 {
1755 set(&mut a, i, b"x");
1756 }
1757 assert_eq!(a.delete_range(100, 29_899), 29_800);
1758 assert_eq!(a.count(), 200);
1759 assert_eq!(read(&a, 99).as_deref(), Some(&b"x"[..]));
1760 assert_eq!(read(&a, 100), None);
1761 assert_eq!(read(&a, 29_899), None);
1762 assert_eq!(read(&a, 29_900).as_deref(), Some(&b"x"[..]));
1763 assert_eq!(a.len(), 30_000);
1764 }
1765
1766 #[test]
1767 fn a_backwards_range_deletes_nothing() {
1768 let mut a = Array::new();
1769 set(&mut a, 5, b"x");
1770 assert_eq!(a.delete_range(9, 4), 0);
1771 assert_eq!(a.count(), 1);
1772 }
1773
1774 #[test]
1781 fn only_a_value_that_prints_back_the_same_becomes_a_number() {
1782 let cases: &[(&[u8], bool)] = &[
1783 (b"0", true),
1784 (b"42", true),
1785 (b"-42", true),
1786 (b"9007199254740993", true),
1787 (b"007", false),
1788 (b"+7", false),
1789 (b"-0", false),
1790 (b" 7", false),
1791 (b"7 ", false),
1792 (b"", false),
1793 ];
1794 for &(val, want) in cases {
1795 let mut a = Array::new();
1796 set(&mut a, 0, val);
1797 let is_int = matches!(a.get(0), Some(Element::Int(_)));
1798 assert_eq!(is_int, want, "{}", String::from_utf8_lossy(val));
1799 assert_eq!(read(&a, 0).as_deref(), Some(val), "round trip");
1800 }
1801 }
1802
1803 #[test]
1805 fn only_a_double_that_prints_back_the_same_is_stored_as_one() {
1806 let cases: &[(&[u8], bool)] = &[
1807 (b"1.0", true),
1808 (b"1.5", true),
1809 (b"-2.25", true),
1810 (b"0.0", true),
1811 (b"3.14", false),
1814 (b"1.10", false),
1815 (b"-0.0", true),
1818 (b"1.", false),
1819 (b".5", false),
1820 (b"1e5", false),
1821 (b"nan", false),
1822 (b"inf", false),
1823 ];
1824 for &(val, want) in cases {
1825 let mut a = Array::new();
1826 set(&mut a, 0, val);
1827 let is_float = matches!(a.get(0), Some(Element::Float(_)));
1828 assert_eq!(is_float, want, "{}", String::from_utf8_lossy(val));
1829 assert_eq!(read(&a, 0).as_deref(), Some(val), "round trip");
1830 }
1831 }
1832
1833 #[test]
1836 fn the_blob_is_compacted_once_enough_of_it_is_dead() {
1837 let mut a = Array::new();
1838 let long = vec![b'a'; 64];
1839 for i in 0..1000 {
1840 set(&mut a, i, &long);
1841 }
1842 let full = a.blob.len();
1843 assert_eq!(full, 64_000);
1844
1845 for i in 0..1000 {
1847 set(&mut a, i, b"short");
1848 }
1849 assert!(a.blob.len() < full / 2, "{} bytes left", a.blob.len());
1850 assert_eq!(a.count(), 1000);
1851 for i in 0..1000 {
1852 assert_eq!(read(&a, i).as_deref(), Some(&b"short"[..]), "at {i}");
1853 }
1854 }
1855
1856 #[test]
1859 fn compaction_keeps_the_values_that_survive_it() {
1860 let mut a = Array::new();
1861 for i in 0..2000u64 {
1862 let val = format!("value number {i} padded out past the inline limit");
1863 set(&mut a, i, val.as_bytes());
1864 }
1865 for i in (0..2000u64).step_by(2) {
1867 a.del(i);
1868 }
1869 assert!(a.dead * 2 < a.blob.len(), "the blob was rewritten");
1870 for i in (1..2000u64).step_by(2) {
1871 let want = format!("value number {i} padded out past the inline limit");
1872 assert_eq!(read(&a, i).as_deref(), Some(want.as_bytes()), "at {i}");
1873 }
1874 }
1875
1876 #[test]
1877 fn a_value_over_the_ceiling_is_an_error_and_not_a_panic() {
1878 let mut a = Array::new();
1879 let huge = vec![b'x'; VALUE_MAX + 1];
1880 let e = a.set(0, &huge).unwrap_err();
1881 assert_eq!(e.code(), Code::Full);
1882 assert_eq!(e.message(), VALUE_TOO_LONG);
1883 assert!(a.is_empty(), "and nothing was written");
1884 }
1885
1886 #[test]
1888 fn a_word_holds_what_it_was_given() {
1889 assert!(Word::EMPTY.is_empty());
1890 for i in [0i64, 1, -1, INT_LO, INT_HI, 12345, -99999] {
1891 let w = Word::from_int(i);
1892 assert!(!w.is_empty());
1893 assert_eq!(w.tag(), TAG_INT);
1894 assert_eq!(w.to_int(), i, "{i}");
1895 }
1896 for d in [0.0f64, 1.5, -2.25, 1e300] {
1897 let bits = d.to_bits() & !TAG_MASK;
1898 let w = Word::from_float_bits(bits);
1899 assert!(!w.is_empty());
1900 assert_eq!(w.tag(), TAG_FLOAT);
1901 assert_eq!(w.to_float().to_bits(), bits);
1902 }
1903 for s in [&b""[..], b"a", b"abc", b"1234567"] {
1904 let w = Word::from_short(s);
1905 assert!(!w.is_empty(), "{s:?}");
1906 assert_eq!(w.tag(), TAG_STR);
1907 assert_eq!(w.to_short().as_bytes(), s);
1908 }
1909 let w = Word::from_blob(4_000_000_000, 1_000_000);
1910 assert_eq!(w.tag(), TAG_BLOB);
1911 assert_eq!(w.blob_span(), (4_000_000_000, 1_000_000));
1912 assert!(!w.is_empty());
1913 }
1914
1915 #[test]
1916 fn what_it_holds_is_what_it_says_it_holds() {
1917 let mut a = Array::new();
1918 assert_eq!(a.memory_bytes(), 0);
1919 for i in 0..1000u64 {
1920 set(&mut a, i * 7, b"a value past the inline limit");
1921 }
1922 let held = a.memory_bytes();
1923 assert!(held > 29_000, "{held} bytes for 29 kilobytes of values");
1924 a.delete_range(0, u64::MAX - 1);
1925 assert!(
1926 a.memory_bytes() < held / 2,
1927 "{} bytes left of {held}",
1928 a.memory_bytes()
1929 );
1930 }
1931
1932 #[test]
1935 fn it_agrees_with_a_map_over_a_scramble_of_writes() {
1936 use std::collections::BTreeMap;
1937
1938 let mut a = Array::new();
1939 let mut want: BTreeMap<u64, Vec<u8>> = BTreeMap::new();
1940 let mut seed = 0x9e37_79b9_7f4a_7c15u64;
1941 let mut next = || {
1942 seed ^= seed << 13;
1943 seed ^= seed >> 7;
1944 seed ^= seed << 17;
1945 seed
1946 };
1947
1948 for step in 0..20_000u64 {
1949 let idx = next() % 20_000;
1950 match step % 5 {
1951 0..=2 => {
1952 let val = format!("v{step}");
1953 let was_new = set(&mut a, idx, val.as_bytes());
1954 assert_eq!(was_new, want.insert(idx, val.into_bytes()).is_none());
1955 }
1956 3 => {
1957 assert_eq!(a.del(idx), want.remove(&idx).is_some());
1958 }
1959 _ => {
1960 let hi = idx + (next() % 500);
1961 let gone = a.delete_range(idx, hi);
1962 let keys: Vec<u64> = want.range(idx..=hi).map(|(k, _)| *k).collect();
1963 assert_eq!(gone, keys.len() as u64);
1964 for k in keys {
1965 want.remove(&k);
1966 }
1967 }
1968 }
1969 assert_eq!(a.count(), want.len() as u64, "count after step {step}");
1970 }
1971
1972 assert_eq!(
1973 a.len(),
1974 want.keys().next_back().map_or(0, |k| k + 1),
1975 "the high water mark"
1976 );
1977 for (&idx, val) in &want {
1978 assert_eq!(read(&a, idx).as_deref(), Some(&val[..]), "at {idx}");
1979 }
1980 }
1981
1982 #[test]
1983 fn a_scan_finds_the_elements_and_steps_over_the_holes() {
1984 let mut a = Array::new();
1985 set(&mut a, 0, b"a");
1986 set(&mut a, 5, b"b");
1987 set(&mut a, SLICE_SIZE * 2 + 7, b"c");
1989
1990 let all = vec![
1991 (0, b"a".to_vec()),
1992 (5, b"b".to_vec()),
1993 (SLICE_SIZE * 2 + 7, b"c".to_vec()),
1994 ];
1995 assert_eq!(scan(&a, 0, INDEX_MAX, usize::MAX), all);
1998 let mut backwards = all.clone();
1999 backwards.reverse();
2000 assert_eq!(scan(&a, INDEX_MAX, 0, usize::MAX), backwards);
2001
2002 assert_eq!(scan(&a, 1, 5, usize::MAX), all[1..2].to_vec());
2005 assert_eq!(scan(&a, 6, SLICE_SIZE, usize::MAX), Vec::new());
2006 assert_eq!(scan(&a, 0, INDEX_MAX, 2), all[..2].to_vec());
2007 assert_eq!(scan(&Array::new(), 0, INDEX_MAX, usize::MAX), Vec::new());
2008 }
2009
2010 #[test]
2013 fn a_scan_reads_both_layouts_the_same_way() {
2014 let mut a = Array::new();
2015 for i in 0..40u64 {
2016 set(&mut a, i, format!("v{i}").as_bytes());
2017 }
2018 for i in (0..40u64).step_by(2) {
2019 a.del(i);
2020 }
2021 let odd: Vec<(u64, Vec<u8>)> = (1..40u64)
2022 .step_by(2)
2023 .map(|i| (i, format!("v{i}").into_bytes()))
2024 .collect();
2025 assert_eq!(scan(&a, 0, 100, usize::MAX), odd);
2026
2027 let mut b = Array::new();
2030 for i in (1..40u64).step_by(2) {
2031 set(&mut b, i, format!("v{i}").as_bytes());
2032 }
2033 assert_eq!(scan(&b, 0, 100, usize::MAX), odd);
2034 }
2035
2036 #[test]
2037 fn the_cursor_moves_only_when_something_appends_to_it() {
2038 let mut a = Array::new();
2039 assert_eq!(a.next_index(), Some(0));
2040 set(&mut a, 0, b"set");
2043 assert_eq!(a.next_index(), Some(0));
2044 assert_eq!(append(&mut a, &[b"x", b"y"]).expect("room"), 1);
2045 assert_eq!(read(&a, 0).as_deref(), Some(&b"x"[..]));
2046 assert_eq!(a.next_index(), Some(2));
2047
2048 a.seek(100);
2050 assert_eq!(a.next_index(), Some(100));
2051 assert_eq!(append(&mut a, &[b"z"]).expect("room"), 100);
2052 assert_eq!(read(&a, 100).as_deref(), Some(&b"z"[..]));
2053 a.seek(0);
2054 assert_eq!(a.next_index(), Some(0));
2055 }
2056
2057 #[test]
2058 fn an_append_that_would_run_off_the_top_writes_nothing() {
2059 let mut a = Array::new();
2060 a.seek(INDEX_MAX - 1);
2061 let e = append(&mut a, &[b"x", b"y", b"z"]).unwrap_err();
2062 assert_eq!(e.code(), Code::Invalid);
2063 assert_eq!(e.message(), INSERT_OVERFLOW);
2064 assert_eq!(a.count(), 0, "and none of the batch landed");
2065
2066 assert_eq!(append(&mut a, &[b"x", b"y"]).expect("room"), INDEX_MAX);
2068 assert_eq!(a.next_index(), None);
2069 assert_eq!(
2070 append(&mut a, &[b"z"]).unwrap_err().message(),
2071 INSERT_OVERFLOW
2072 );
2073 }
2074
2075 #[test]
2076 fn a_ring_wraps_round_at_its_size() {
2077 let mut a = Array::new();
2078 assert_eq!(ring(&mut a, 3, &[b"a", b"b", b"c"]), 2);
2079 assert_eq!(ring(&mut a, 3, &[b"d", b"e"]), 1);
2080 assert_eq!(a.len(), 3, "it never grows past the size it was given");
2081 assert_eq!(a.count(), 3);
2082 assert_eq!(read(&a, 0).as_deref(), Some(&b"d"[..]));
2083 assert_eq!(read(&a, 1).as_deref(), Some(&b"e"[..]));
2084 assert_eq!(read(&a, 2).as_deref(), Some(&b"c"[..]));
2085 }
2086
2087 #[test]
2091 fn a_ring_that_changes_size_is_renumbered_oldest_first() {
2092 let mut a = Array::new();
2093 ring(&mut a, 3, &[b"a", b"b", b"c", b"d", b"e"]);
2094 assert_eq!(ring(&mut a, 5, &[b"f"]), 3);
2096 assert_eq!(
2097 (0..4).map(|i| read(&a, i)).collect::<Vec<_>>(),
2098 vec![
2099 Some(b"c".to_vec()),
2100 Some(b"d".to_vec()),
2101 Some(b"e".to_vec()),
2102 Some(b"f".to_vec())
2103 ]
2104 );
2105
2106 let mut b = Array::new();
2108 ring(&mut b, 3, &[b"a", b"b", b"c", b"d", b"e"]);
2109 assert_eq!(ring(&mut b, 2, &[b"f"]), 0);
2110 assert_eq!(b.count(), 2);
2111 assert_eq!(read(&b, 0).as_deref(), Some(&b"f"[..]));
2112 assert_eq!(read(&b, 1).as_deref(), Some(&b"e"[..]));
2113 }
2114
2115 #[test]
2118 fn a_hole_cuts_what_a_resize_keeps() {
2119 let mut a = Array::new();
2120 ring(&mut a, 4, &[b"a", b"b", b"c", b"d", b"e"]);
2121 a.del(2);
2123 assert_eq!(ring(&mut a, 8, &[b"f"]), 2);
2124 assert_eq!(
2127 (0..3).map(|i| read(&a, i)).collect::<Vec<_>>(),
2128 vec![
2129 Some(b"d".to_vec()),
2130 Some(b"e".to_vec()),
2131 Some(b"f".to_vec())
2132 ]
2133 );
2134 }
2135
2136 #[test]
2137 fn the_last_items_walk_wraps_and_reports_the_holes() {
2138 let mut a = Array::new();
2139 ring(&mut a, 4, &[b"a", b"b", b"c", b"d", b"e"]);
2140 assert_eq!(
2143 last(&a, 3, false),
2144 vec![
2145 Some(b"c".to_vec()),
2146 Some(b"d".to_vec()),
2147 Some(b"e".to_vec())
2148 ]
2149 );
2150 assert_eq!(
2151 last(&a, 3, true),
2152 vec![
2153 Some(b"e".to_vec()),
2154 Some(b"d".to_vec()),
2155 Some(b"c".to_vec())
2156 ]
2157 );
2158 assert_eq!(last(&a, 99, false).len(), 4);
2160 assert_eq!(last(&a, 0, false), Vec::new());
2161 assert_eq!(last(&Array::new(), 5, false), Vec::new());
2162
2163 let mut b = Array::new();
2166 set(&mut b, 0, b"a");
2167 set(&mut b, 2, b"c");
2168 assert_eq!(last(&b, 5, false), vec![None, Some(b"c".to_vec())]);
2169 }
2170
2171 #[test]
2174 fn a_copy_of_an_array_remembers_the_cursor() {
2175 let mut a = Array::new();
2176 append(&mut a, &[b"x", b"y"]).expect("room");
2177 let mut b = a.clone();
2178 assert_eq!(b.next_index(), Some(2));
2179 assert_eq!(append(&mut b, &[b"z"]).expect("room"), 2);
2180 assert_eq!(a.next_index(), Some(2), "and the two do not share it");
2181 }
2182
2183 fn round_trip(a: &Array) -> Array {
2185 let mut buf = Vec::new();
2186 a.freeze(&mut buf);
2187 let back = Array::thaw(&buf).expect("what freeze wrote");
2188 assert_eq!(back.count(), a.count(), "the population");
2189 assert_eq!(back.len(), a.len(), "the high water mark");
2190 assert_eq!(back.next_index(), a.next_index(), "the insert cursor");
2191 assert_eq!(back.slices.len(), a.slices.len(), "the slice count");
2192 for ((id, was), (back_id, now)) in a.slices.iter().zip(&back.slices) {
2193 assert_eq!(id, back_id, "the slice ids");
2194 assert_eq!(was.count, now.count, "slice {id} holds the same number");
2195 assert_eq!(
2196 matches!(was.layout, Layout::Dense { .. }),
2197 matches!(now.layout, Layout::Dense { .. }),
2198 "slice {id} came back in the layout it left in"
2199 );
2200 }
2201 assert_eq!(
2202 scan(&back, 0, u64::MAX, usize::MAX),
2203 scan(a, 0, u64::MAX, usize::MAX)
2204 );
2205 back
2206 }
2207
2208 #[test]
2209 fn a_frozen_array_comes_back_with_every_value_it_held() {
2210 let mut a = Array::new();
2211 set(&mut a, 0, b"12345");
2214 set(&mut a, 1, b"1.5");
2215 set(&mut a, 2, b"short");
2216 set(
2217 &mut a,
2218 3,
2219 b"a value well past the seven bytes a word can inline",
2220 );
2221 set(&mut a, 9_000_000_000_000, b"a long way up the index space");
2222 let back = round_trip(&a);
2223 assert_eq!(read(&back, 0).as_deref(), Some(&b"12345"[..]));
2224 assert_eq!(read(&back, 1).as_deref(), Some(&b"1.5"[..]));
2225 assert_eq!(read(&back, 2).as_deref(), Some(&b"short"[..]));
2226 assert_eq!(
2227 read(&back, 3).as_deref(),
2228 Some(&b"a value well past the seven bytes a word can inline"[..])
2229 );
2230 assert_eq!(
2231 read(&back, 9_000_000_000_000).as_deref(),
2232 Some(&b"a long way up the index space"[..])
2233 );
2234 assert_eq!(read(&back, 4), None, "and a hole is still a hole");
2235 assert_eq!(back.get(0), Some(Element::Int(12345)), "still an integer");
2236 assert_eq!(back.get(1), Some(Element::Float(1.5)), "still a double");
2237
2238 round_trip(&Array::new());
2239 }
2240
2241 #[test]
2242 fn both_layouts_come_back_in_the_layout_they_left_in() {
2243 let mut dense = Array::new();
2245 for i in 0..=SPARSE_MAX as u64 {
2246 set(&mut dense, i, b"x");
2247 }
2248 assert!(matches!(dense.slices[0].1.layout, Layout::Dense { .. }));
2249 round_trip(&dense);
2250
2251 let mut holed = dense.clone();
2254 for i in 2..5 {
2255 holed.del(i);
2256 }
2257 assert!(matches!(holed.slices[0].1.layout, Layout::Dense { .. }));
2258 assert_eq!(holed.count(), 8);
2259 let back = round_trip(&holed);
2260 assert_eq!(read(&back, 1).as_deref(), Some(&b"x"[..]));
2261 assert_eq!(read(&back, 4), None);
2262
2263 let mut sparse = Array::new();
2265 for i in 0..40 {
2266 set(&mut sparse, i * 100, b"x");
2267 }
2268 assert!(matches!(sparse.slices[0].1.layout, Layout::Sparse { .. }));
2269 round_trip(&sparse);
2270 }
2271
2272 #[test]
2273 fn freezing_an_array_leaves_the_dead_blob_bytes_behind() {
2274 let mut a = Array::new();
2275 let long = vec![b'v'; 200];
2276 for _ in 0..8 {
2279 set(&mut a, 0, &long);
2280 }
2281 assert!(a.dead > 0, "there is dead space to leave behind");
2282 let mut buf = Vec::new();
2283 a.freeze(&mut buf);
2284 let back = Array::thaw(&buf).expect("what freeze wrote");
2285 assert_eq!(back.dead, 0, "a demotion is a compaction");
2286 assert_eq!(back.blob.len(), a.blob.len() - a.dead);
2287 assert_eq!(read(&back, 0).as_deref(), Some(&long[..]));
2288 assert!(
2289 buf.len() < a.blob.len(),
2290 "and the dead bytes never went out"
2291 );
2292 }
2293
2294 #[test]
2295 fn a_frozen_array_keeps_the_insert_cursor() {
2296 let mut a = Array::new();
2297 append(&mut a, &[b"x", b"y", b"z"]).expect("room");
2298 let mut back = round_trip(&a);
2299 assert_eq!(back.next_index(), Some(3));
2300 assert_eq!(append(&mut back, &[b"w"]).expect("room"), 3);
2301
2302 let mut untouched = Array::new();
2305 set(&mut untouched, 99, b"x");
2306 let mut back = round_trip(&untouched);
2307 assert_eq!(back.next_index(), Some(0), "a cursor nothing has moved");
2308 assert_eq!(append(&mut back, &[b"first"]).expect("room"), 0);
2309 }
2310
2311 #[test]
2312 fn a_frozen_array_that_arrives_damaged_is_an_error_and_not_a_panic() {
2313 let mut a = Array::new();
2314 for i in 0..200u64 {
2315 set(
2316 &mut a,
2317 i * 7,
2318 format!("value:{i:04} and enough bytes to reach the blob").as_bytes(),
2319 );
2320 }
2321 let mut buf = Vec::new();
2322 a.freeze(&mut buf);
2323 assert!(Array::thaw(&buf).is_ok(), "the body it wrote reads back");
2324
2325 assert!(Array::thaw(&[]).is_err(), "nothing at all");
2326 assert!(Array::thaw(&[99]).is_err(), "a form nobody wrote");
2327 for cut in 1..buf.len().min(96) {
2328 assert!(Array::thaw(&buf[..cut]).is_err(), "cut at {cut}");
2329 }
2330 for at in 0..buf.len().min(96) {
2333 for bit in 0..8 {
2334 let mut bad = buf.clone();
2335 bad[at] ^= 1 << bit;
2336 let _ = Array::thaw(&bad);
2339 }
2340 }
2341 }
2342}