1use rudb_common::{Error, Result};
34use rudb_encoding::bitpack;
35
36use crate::bits::Rank;
37use crate::rid::Rid;
38
39pub const DENSE_THRESHOLD: u64 = 8;
47
48#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50pub enum Form {
51 Identity,
53 Dense,
55 Sorted,
57 Permuted,
59}
60
61impl Form {
62 #[must_use]
64 pub fn tag(self) -> u8 {
65 match self {
66 Self::Identity => 0,
67 Self::Dense => 1,
68 Self::Sorted => 2,
69 Self::Permuted => 3,
70 }
71 }
72
73 #[must_use]
75 pub fn label(self) -> &'static str {
76 match self {
77 Self::Identity => "identity",
78 Self::Dense => "dense",
79 Self::Sorted => "sorted",
80 Self::Permuted => "permuted",
81 }
82 }
83
84 pub fn from_tag(tag: u8) -> Result<Self> {
93 match tag {
94 0 => Ok(Self::Identity),
95 1 => Ok(Self::Dense),
96 2 => Ok(Self::Sorted),
97 3 => Ok(Self::Permuted),
98 _ => Err(malformed(format!("key map form {tag} is not one this build knows"))),
99 }
100 }
101}
102
103#[derive(Debug, Clone, Copy, PartialEq, Eq)]
110pub struct Observed {
111 pub rows: u64,
113 pub nulls: u64,
115 pub distinct: bool,
117 pub sorted: bool,
119 pub min: Option<i128>,
121 pub max: Option<i128>,
123}
124
125impl Observed {
126 #[must_use]
132 pub fn usable_as_parent(&self) -> bool {
133 self.distinct
134 }
135}
136
137#[derive(Debug, Clone)]
139enum Body {
140 Identity {
141 base: i128,
142 count: u64,
143 },
144 Dense {
145 base: i128,
146 range: u64,
147 bits: Vec<u64>,
148 rank: Rank,
149 },
150 Sorted {
151 base: i128,
154 key_width: usize,
156 keys: Vec<u8>,
158 rid_width: usize,
160 perm: Vec<u8>,
162 count: u64,
163 },
164 Permuted {
165 base: i128,
166 range: u64,
167 bits: Vec<u64>,
168 rank: Rank,
169 rid_width: usize,
171 perm: Vec<u8>,
173 },
174}
175
176#[derive(Debug, Clone)]
178pub struct KeyMap {
179 body: Body,
180 observed: Observed,
181}
182
183impl KeyMap {
184 pub fn build(keys: &[Option<i128>]) -> Result<Self> {
202 let mut observed = observe(keys);
203 if !observed.distinct {
207 return Ok(Self { body: Body::Identity { base: 0, count: 0 }, observed });
208 }
209 Ok(match plan(&observed)? {
210 Plan::Empty => Self { body: Body::Identity { base: 0, count: 0 }, observed },
211 Plan::Identity { base, count } => {
212 Self { body: Body::Identity { base, count }, observed }
213 }
214 Plan::Dense { base, range } => Self { body: dense(keys, base, range)?, observed },
215 Plan::Permuted { base, range } => {
216 let mut bits = DenseBits::new(base, range);
217 for key in keys.iter().flatten() {
218 if !bits.mark(*key)? {
219 observed.distinct = false;
220 return Ok(Self { body: Body::Identity { base: 0, count: 0 }, observed });
221 }
222 }
223 let mut perm = Permutation::new(bits, keys.len())?;
224 for (rid, key) in keys.iter().enumerate() {
225 if let Some(key) = *key {
226 perm.place(key, rid)?;
227 }
228 }
229 Self { body: perm.finish()?, observed }
230 }
231 Plan::Sorted { base } => {
232 let (body, distinct) = sorted(keys, base, observed.rows)?;
236 observed.distinct = distinct;
237 Self { body, observed }
238 }
239 })
240 }
241
242 pub fn build_from<K: Keys + ?Sized>(keys: &K) -> Result<Self> {
262 let mut observer = Observer::new();
263 keys.scan(&mut |key| {
264 observer.push(key);
265 Ok(())
266 })?;
267 let mut observed = observer.observed;
268 if !observed.distinct {
276 return Ok(Self { body: Body::Identity { base: 0, count: 0 }, observed });
277 }
278 Ok(match plan(&observed)? {
279 Plan::Empty => Self { body: Body::Identity { base: 0, count: 0 }, observed },
280 Plan::Identity { base, count } => {
281 Self { body: Body::Identity { base, count }, observed }
282 }
283 Plan::Dense { base, range } => {
284 let mut bits = DenseBits::new(base, range);
285 keys.scan(&mut |key| match key {
286 Some(key) => bits.push(key),
287 None => Ok(()),
288 })?;
289 Self { body: bits.finish(), observed }
290 }
291 Plan::Permuted { base, range } => {
292 let mut bits = DenseBits::new(base, range);
298 let mut repeated = false;
299 keys.scan(&mut |key| {
300 if let Some(key) = key {
301 repeated |= !bits.mark(key)?;
302 }
303 Ok(())
304 })?;
305 if repeated {
306 observed.distinct = false;
307 return Ok(Self { body: Body::Identity { base: 0, count: 0 }, observed });
308 }
309 let rows = observed.rows + observed.nulls;
310 let rows = usize::try_from(rows)
311 .map_err(|_| malformed("the column is too long for this machine"))?;
312 let mut perm = Permutation::new(bits, rows)?;
313 let mut rid = 0_usize;
314 keys.scan(&mut |key| {
315 if let Some(key) = key {
316 perm.place(key, rid)?;
317 }
318 rid += 1;
319 Ok(())
320 })?;
321 Self { body: perm.finish()?, observed }
322 }
323 Plan::Sorted { base } => {
324 let mut held = Vec::with_capacity(
325 usize::try_from(observed.rows + observed.nulls).unwrap_or_default(),
326 );
327 keys.scan(&mut |key| {
328 held.push(key);
329 Ok(())
330 })?;
331 let (body, distinct) = sorted(&held, base, observed.rows)?;
332 observed.distinct = distinct;
333 Self { body, observed }
334 }
335 })
336 }
337
338 #[must_use]
340 pub fn form(&self) -> Form {
341 match self.body {
342 Body::Identity { .. } => Form::Identity,
343 Body::Dense { .. } => Form::Dense,
344 Body::Sorted { .. } => Form::Sorted,
345 Body::Permuted { .. } => Form::Permuted,
346 }
347 }
348
349 #[must_use]
359 pub fn span(&self) -> Option<(i128, u64)> {
360 match self.body {
361 Body::Identity { base, count } => Some((base, count)),
362 Body::Dense { base, range, .. } | Body::Permuted { base, range, .. } => {
363 Some((base, range))
364 }
365 Body::Sorted { .. } => None,
366 }
367 }
368
369 #[must_use]
371 pub fn observed(&self) -> &Observed {
372 &self.observed
373 }
374
375 pub(crate) fn base(&self) -> i128 {
377 match &self.body {
378 Body::Identity { base, .. }
379 | Body::Dense { base, .. }
380 | Body::Sorted { base, .. }
381 | Body::Permuted { base, .. } => *base,
382 }
383 }
384
385 pub(crate) fn write_body(&self, out: &mut Vec<u8>) -> Result<()> {
391 match &self.body {
392 Body::Identity { .. } => Ok(()),
393 Body::Dense { range, bits, rank, .. } => {
394 out.extend_from_slice(&range.to_le_bytes());
395 for word in bits {
396 out.extend_from_slice(&word.to_le_bytes());
397 }
398 rank.write(out);
399 Ok(())
400 }
401 Body::Sorted { key_width, keys, rid_width, perm, .. } => {
402 let widths = [*key_width, *rid_width];
405 for width in widths {
406 let width = u8::try_from(width)
407 .map_err(|_| malformed("a sorted key map's width does not fit a byte"))?;
408 out.push(width);
409 }
410 out.extend_from_slice(keys);
411 out.extend_from_slice(perm);
412 Ok(())
413 }
414 Body::Permuted { range, bits, rank, rid_width, perm, .. } => {
415 out.extend_from_slice(&range.to_le_bytes());
419 for word in bits {
420 out.extend_from_slice(&word.to_le_bytes());
421 }
422 rank.write(out);
423 let width = u8::try_from(*rid_width)
424 .map_err(|_| malformed("a permuted key map's width does not fit a byte"))?;
425 out.push(width);
426 out.extend_from_slice(perm);
427 Ok(())
428 }
429 }
430 }
431
432 pub(crate) fn read_body(
444 form: Form,
445 base: i128,
446 mut observed: Observed,
447 body: &[u8],
448 ) -> Result<Self> {
449 match form {
450 Form::Identity => {
451 if !body.is_empty() {
452 return Err(malformed("an identity key map has no body"));
453 }
454 if observed.rows > 0 {
455 observed.max = Some(
456 base.checked_add(i128::from(observed.rows) - 1)
457 .ok_or_else(|| malformed("an identity key map's range overflows"))?,
458 );
459 }
460 Ok(Self { body: Body::Identity { base, count: observed.rows }, observed })
461 }
462 Form::Dense => {
463 let Some(head) = body.get(..size_of::<u64>()) else {
464 return Err(malformed("a dense key map has no range"));
465 };
466 let range = u64::from_le_bytes(head.try_into().expect("eight bytes"));
467 let Ok(range_usize) = usize::try_from(range) else {
468 return Err(malformed("a dense key map's range does not fit this machine"));
469 };
470 let words = range_usize.div_ceil(64);
471 let bitmap = words * size_of::<u64>();
472 let rest = &body[size_of::<u64>()..];
473 if rest.len() < bitmap {
474 return Err(malformed("a dense key map's bitmap is shorter than its range"));
475 }
476 let bits: Vec<u64> = rest[..bitmap]
477 .chunks_exact(size_of::<u64>())
478 .map(|word| u64::from_le_bytes(word.try_into().expect("eight bytes")))
479 .collect();
480 let rank = Rank::read(&rest[bitmap..], words)?;
481 observed.max = Some(
482 base.checked_add(i128::from(range) - 1)
483 .ok_or_else(|| malformed("a dense key map's range overflows"))?,
484 );
485 Ok(Self { body: Body::Dense { base, range, bits, rank }, observed })
486 }
487 Form::Sorted => {
488 if body.len() < 2 {
489 return Err(malformed("a sorted key map has no widths"));
490 }
491 let key_width = usize::from(body[0]);
492 let rid_width = usize::from(body[1]);
493 if key_width == 0 || key_width > 64 || rid_width == 0 || rid_width > 64 {
494 return Err(malformed("a sorted key map's width is not one a u64 can take"));
495 }
496 let count = observed.rows;
497 let Ok(count_usize) = usize::try_from(count) else {
498 return Err(malformed(
499 "a sorted key map holds more keys than this machine can",
500 ));
501 };
502 let key_bytes = (count_usize * key_width).div_ceil(8);
503 let perm_bytes = (count_usize * rid_width).div_ceil(8);
504 let rest = &body[2..];
505 if rest.len() != key_bytes + perm_bytes {
506 return Err(malformed(
507 "a sorted key map's arrays are not the size its widths and count imply",
508 ));
509 }
510 let keys = rest[..key_bytes].to_vec();
511 let perm = rest[key_bytes..].to_vec();
512 if count > 0 {
513 let largest = bitpack::tail_at(&keys, key_width, count_usize - 1)?;
514 observed.max =
515 Some(base.checked_add(i128::from(largest)).ok_or_else(|| {
516 malformed("a sorted key map's largest key overflows")
517 })?);
518 }
519 Ok(Self {
520 body: Body::Sorted { base, key_width, keys, rid_width, perm, count },
521 observed,
522 })
523 }
524 Form::Permuted => {
525 let Some(head) = body.get(..size_of::<u64>()) else {
526 return Err(malformed("a permuted key map has no range"));
527 };
528 let range = u64::from_le_bytes(head.try_into().expect("eight bytes"));
529 let Ok(range_usize) = usize::try_from(range) else {
530 return Err(malformed("a permuted key map's range does not fit this machine"));
531 };
532 let words = range_usize.div_ceil(64);
533 let bitmap = words * size_of::<u64>();
534 let (blocks, superblocks) = Rank::shape(words);
535 let ranks = superblocks * size_of::<u32>() + blocks * size_of::<u16>();
536 let rest = &body[size_of::<u64>()..];
537 if rest.len() < bitmap + ranks + 1 {
538 return Err(malformed("a permuted key map is shorter than its range implies"));
539 }
540 let bits: Vec<u64> = rest[..bitmap]
541 .chunks_exact(size_of::<u64>())
542 .map(|word| u64::from_le_bytes(word.try_into().expect("eight bytes")))
543 .collect();
544 let rank = Rank::read(&rest[bitmap..bitmap + ranks], words)?;
545 let rid_width = usize::from(rest[bitmap + ranks]);
546 if rid_width == 0 || rid_width > 64 {
547 return Err(malformed("a permuted key map's width is not one a u64 can take"));
548 }
549 let Ok(count) = usize::try_from(observed.rows) else {
550 return Err(malformed(
551 "a permuted key map holds more keys than this machine can",
552 ));
553 };
554 let perm = rest[bitmap + ranks + 1..].to_vec();
555 if perm.len() != (count * rid_width).div_ceil(8) {
556 return Err(malformed(
557 "a permuted key map's permutation is not the size its width and count imply",
558 ));
559 }
560 observed.max = Some(
561 base.checked_add(i128::from(range) - 1)
562 .ok_or_else(|| malformed("a permuted key map's range overflows"))?,
563 );
564 Ok(Self {
565 body: Body::Permuted { base, range, bits, rank, rid_width, perm },
566 observed,
567 })
568 }
569 }
570 }
571
572 #[must_use]
574 pub fn len(&self) -> u64 {
575 match &self.body {
576 Body::Identity { count, .. } | Body::Sorted { count, .. } => *count,
577 Body::Dense { .. } | Body::Permuted { .. } => self.observed.rows,
578 }
579 }
580
581 #[must_use]
583 pub fn is_empty(&self) -> bool {
584 self.len() == 0
585 }
586
587 #[must_use]
592 pub fn bytes(&self) -> usize {
593 match &self.body {
594 Body::Identity { .. } => size_of::<i128>() + size_of::<u64>(),
595 Body::Dense { bits, rank, .. } => bits.len() * size_of::<u64>() + rank.bytes(),
596 Body::Sorted { keys, perm, .. } => keys.len() + perm.len(),
597 Body::Permuted { bits, rank, perm, .. } => {
598 bits.len() * size_of::<u64>() + rank.bytes() + perm.len()
599 }
600 }
601 }
602
603 pub fn rows_of_span(&self, held: &[u64], rows: u64) -> Result<Option<Vec<u64>>> {
623 let words = usize::try_from(rows.div_ceil(64)).unwrap_or(usize::MAX);
624 let Some((_, range)) = self.span() else { return Ok(None) };
625 let span_words = usize::try_from(range.div_ceil(64)).unwrap_or(usize::MAX);
626 if held.len() < span_words || held[span_words..].iter().any(|&word| word != 0) {
627 return Ok(None);
628 }
629 if range % 64 != 0 && held[span_words - 1] >> (range % 64) != 0 {
631 return Ok(None);
632 }
633 let held = &held[..span_words];
634 let mut out = vec![0_u64; words];
635 match &self.body {
636 Body::Identity { count, .. } => {
637 if *count > rows {
638 return Ok(None);
639 }
640 out[..span_words].copy_from_slice(held);
641 }
642 Body::Dense { bits, .. } => {
643 if bits.len() < held.len() {
644 return Ok(None);
645 }
646 let mut before = 0_u64;
647 for (&keys, &present) in held.iter().zip(bits) {
648 if keys & !present != 0 {
649 return Ok(None);
650 }
651 let mut left = keys;
652 while left != 0 {
653 let below = (1_u64 << left.trailing_zeros()) - 1;
654 let rid = before + u64::from((present & below).count_ones());
655 let Some(word) = out.get_mut((rid / 64) as usize) else { return Ok(None) };
656 *word |= 1 << (rid % 64);
657 left &= left - 1;
658 }
659 before += u64::from(present.count_ones());
660 }
661 }
662 Body::Permuted { bits, rid_width, perm, .. } => {
663 if bits.len() < held.len() {
664 return Ok(None);
665 }
666 let mut before = 0_u64;
667 for (&keys, &present) in held.iter().zip(bits) {
668 if keys & !present != 0 {
669 return Ok(None);
670 }
671 let mut left = keys;
672 while left != 0 {
673 let below = (1_u64 << left.trailing_zeros()) - 1;
674 let place = before + u64::from((present & below).count_ones());
675 #[expect(
676 clippy::cast_possible_truncation,
677 reason = "a rank is below the key count, which the build checked fits a usize"
678 )]
679 let rid = bitpack::tail_at(perm, *rid_width, place as usize)?;
680 let Some(word) = out.get_mut((rid / 64) as usize) else { return Ok(None) };
681 *word |= 1 << (rid % 64);
682 left &= left - 1;
683 }
684 before += u64::from(present.count_ones());
685 }
686 }
687 Body::Sorted { .. } => return Ok(None),
688 }
689 if !rows.is_multiple_of(64) && out.last().is_some_and(|&word| word >> (rows % 64) != 0) {
690 return Ok(None);
691 }
692 Ok(Some(out))
693 }
694
695 pub fn lookup(&self, key: i128) -> Result<Option<Rid>> {
705 match &self.body {
706 Body::Identity { base, count } => {
707 let Some(offset) = key.checked_sub(*base) else {
708 return Ok(None);
709 };
710 match u64::try_from(offset) {
711 Ok(rid) if rid < *count => Ok(Some(rid)),
712 _ => Ok(None),
713 }
714 }
715 Body::Dense { base, range, bits, rank } => {
716 let Some(offset) = key.checked_sub(*base) else {
717 return Ok(None);
718 };
719 let Ok(offset) = u64::try_from(offset) else {
720 return Ok(None);
721 };
722 if offset >= *range {
723 return Ok(None);
724 }
725 #[expect(
726 clippy::cast_possible_truncation,
727 reason = "the build checked the range fits a usize"
728 )]
729 let at = offset as usize;
730 if bits[at / 64] >> (at % 64) & 1 == 0 {
731 return Ok(None);
732 }
733 Ok(Some(rank.rank(bits, at)))
734 }
735 Body::Permuted { base, range, bits, rank, rid_width, perm } => {
736 let Some(offset) = key.checked_sub(*base) else {
737 return Ok(None);
738 };
739 let Ok(offset) = u64::try_from(offset) else {
740 return Ok(None);
741 };
742 if offset >= *range {
743 return Ok(None);
744 }
745 #[expect(
746 clippy::cast_possible_truncation,
747 reason = "the build checked the range fits a usize"
748 )]
749 let at = offset as usize;
750 if bits[at / 64] >> (at % 64) & 1 == 0 {
751 return Ok(None);
752 }
753 #[expect(
754 clippy::cast_possible_truncation,
755 reason = "a rank is below the key count, which the build checked fits a usize"
756 )]
757 let place = rank.rank(bits, at) as usize;
758 Ok(Some(bitpack::tail_at(perm, *rid_width, place)?))
759 }
760 Body::Sorted { base, key_width, keys, rid_width, perm, count } => {
761 let Some(offset) = key.checked_sub(*base) else {
762 return Ok(None);
763 };
764 let Ok(wanted) = u64::try_from(offset) else {
765 return Ok(None);
766 };
767 #[expect(
768 clippy::cast_possible_truncation,
769 reason = "the build refused a column wider than a usize of rows"
770 )]
771 let len = *count as usize;
772 let mut low = 0_usize;
777 let mut high = len;
778 while low < high {
779 let mid = low + (high - low) / 2;
780 let at = bitpack::tail_at(keys, *key_width, mid)?;
781 if at < wanted {
782 low = mid + 1;
783 } else {
784 high = mid;
785 }
786 }
787 if low >= len || bitpack::tail_at(keys, *key_width, low)? != wanted {
788 return Ok(None);
789 }
790 Ok(Some(bitpack::tail_at(perm, *rid_width, low)?))
791 }
792 }
793 }
794}
795
796pub trait Keys {
806 fn scan(&self, each: &mut dyn FnMut(Option<i128>) -> Result<()>) -> Result<()>;
813}
814
815impl Keys for [Option<i128>] {
816 fn scan(&self, each: &mut dyn FnMut(Option<i128>) -> Result<()>) -> Result<()> {
817 for key in self {
818 each(*key)?;
819 }
820 Ok(())
821 }
822}
823
824enum Plan {
830 Empty,
831 Identity { base: i128, count: u64 },
832 Dense { base: i128, range: u64 },
833 Permuted { base: i128, range: u64 },
834 Sorted { base: i128 },
835}
836
837fn plan(observed: &Observed) -> Result<Plan> {
839 if observed.rows == 0 {
843 return Ok(Plan::Empty);
844 }
845 let (Some(min), Some(max)) = (observed.min, observed.max) else {
846 return Err(malformed("a column with keys in it reported no minimum"));
850 };
851 let range = range_of(min, max)?;
852
853 let positional = observed.distinct && observed.sorted && observed.nulls == 0;
860
861 if positional && range == observed.rows {
862 return Ok(Plan::Identity { base: min, count: observed.rows });
866 }
867
868 let compact = usize::try_from(range).is_ok() && range / observed.rows < DENSE_THRESHOLD;
871 if positional && compact {
872 return Ok(Plan::Dense { base: min, range });
873 }
874
875 if observed.distinct && compact {
881 return Ok(Plan::Permuted { base: min, range });
882 }
883
884 Ok(Plan::Sorted { base: min })
885}
886
887struct Observer {
892 observed: Observed,
893 previous: Option<i128>,
894}
895
896impl Observer {
897 fn new() -> Self {
898 Self {
899 observed: Observed {
900 rows: 0,
901 nulls: 0,
902 distinct: true,
903 sorted: true,
904 min: None,
905 max: None,
906 },
907 previous: None,
908 }
909 }
910
911 fn push(&mut self, key: Option<i128>) {
918 let Some(key) = key else {
919 self.observed.nulls += 1;
920 return;
921 };
922 self.observed.rows += 1;
923 self.observed.min = Some(self.observed.min.map_or(key, |held| held.min(key)));
924 self.observed.max = Some(self.observed.max.map_or(key, |held| held.max(key)));
925 if let Some(previous) = self.previous {
926 if key < previous {
927 self.observed.sorted = false;
928 } else if key == previous {
929 self.observed.distinct = false;
930 }
931 }
932 self.previous = Some(key);
933 }
934}
935
936fn observe(keys: &[Option<i128>]) -> Observed {
938 let mut observer = Observer::new();
939 for key in keys {
940 observer.push(*key);
941 }
942 observer.observed
943}
944
945fn range_of(min: i128, max: i128) -> Result<u64> {
955 let span = max.wrapping_sub(min) as u128;
956 u64::try_from(span)
957 .ok()
958 .and_then(|span| span.checked_add(1))
959 .ok_or_else(|| malformed("the key column spans more than a u64 of values"))
960}
961
962fn offset_of(key: i128, base: i128) -> Result<u64> {
968 let offset = key
969 .checked_sub(base)
970 .ok_or_else(|| malformed("a key is further from the base than an i128 holds"))?;
971 u64::try_from(offset)
972 .map_err(|_| malformed("a key is below the base or further from it than a u64 holds"))
973}
974
975struct DenseBits {
981 base: i128,
982 range: u64,
983 bits: Vec<u64>,
984 previous: Option<i128>,
985}
986
987impl DenseBits {
988 fn new(base: i128, range: u64) -> Self {
989 #[expect(
990 clippy::cast_possible_truncation,
991 reason = "the caller checked the range fits a usize"
992 )]
993 let range_usize = range as usize;
994 Self { base, range, bits: vec![0_u64; range_usize.div_ceil(64)], previous: None }
995 }
996
997 fn push(&mut self, key: i128) -> Result<()> {
998 debug_assert!(
999 self.previous.is_none_or(|held| key > held),
1000 "the bitmap form needs a distinct ascending column, because a rank is a count of keys below a value and that is a rid only there"
1001 );
1002 self.previous = Some(key);
1003 let offset = offset_of(key, self.base)?;
1004 #[expect(
1005 clippy::cast_possible_truncation,
1006 reason = "the caller checked the range fits a usize and the offset is inside it"
1007 )]
1008 let at = offset as usize;
1009 self.bits[at / 64] |= 1 << (at % 64);
1010 Ok(())
1011 }
1012
1013 fn finish(self) -> Body {
1014 let rank = Rank::build(&self.bits);
1015 Body::Dense { base: self.base, range: self.range, bits: self.bits, rank }
1016 }
1017
1018 fn mark(&mut self, key: i128) -> Result<bool> {
1020 let offset = offset_of(key, self.base)?;
1021 #[expect(
1022 clippy::cast_possible_truncation,
1023 reason = "the caller checked the range fits a usize and the offset is inside it"
1024 )]
1025 let at = offset as usize;
1026 let bit = 1 << (at % 64);
1027 let fresh = self.bits[at / 64] & bit == 0;
1028 self.bits[at / 64] |= bit;
1029 Ok(fresh)
1030 }
1031}
1032
1033struct Permutation {
1039 base: i128,
1040 range: u64,
1041 bits: Vec<u64>,
1042 rank: Rank,
1043 places: Vec<u64>,
1044 rid_width: usize,
1045}
1046
1047impl Permutation {
1048 fn new(bits: DenseBits, rows: usize) -> Result<Self> {
1050 let keys: u64 = bits.bits.iter().map(|word| u64::from(word.count_ones())).sum();
1051 let keys =
1052 usize::try_from(keys).map_err(|_| malformed("too many keys for this machine"))?;
1053 let largest = u64::try_from(rows.saturating_sub(1))
1054 .map_err(|_| malformed("the column is too long for a rid"))?;
1055 let rank = Rank::build(&bits.bits);
1056 Ok(Self {
1057 base: bits.base,
1058 range: bits.range,
1059 bits: bits.bits,
1060 rank,
1061 places: vec![0; keys],
1062 rid_width: width_for(largest),
1063 })
1064 }
1065
1066 fn place(&mut self, key: i128, rid: usize) -> Result<()> {
1068 let offset = offset_of(key, self.base)?;
1069 #[expect(
1070 clippy::cast_possible_truncation,
1071 reason = "the offset is inside a range the caller checked fits a usize"
1072 )]
1073 let at = offset as usize;
1074 let place = usize::try_from(self.rank.rank(&self.bits, at))
1075 .map_err(|_| malformed("a rank past what this machine can index"))?;
1076 let rid = u64::try_from(rid).map_err(|_| malformed("the column is too long for a rid"))?;
1077 let slot = self
1078 .places
1079 .get_mut(place)
1080 .ok_or_else(|| malformed("a key was placed that the bitmap does not hold"))?;
1081 *slot = rid;
1082 Ok(())
1083 }
1084
1085 fn finish(self) -> Result<Body> {
1086 let mut perm = Vec::new();
1087 bitpack::pack_linear(&self.places, self.rid_width, &mut perm)?;
1090 Ok(Body::Permuted {
1091 base: self.base,
1092 range: self.range,
1093 bits: self.bits,
1094 rank: self.rank,
1095 rid_width: self.rid_width,
1096 perm,
1097 })
1098 }
1099}
1100
1101fn dense(keys: &[Option<i128>], base: i128, range: u64) -> Result<Body> {
1102 let mut bits = DenseBits::new(base, range);
1103 for key in keys.iter().flatten() {
1104 bits.push(*key)?;
1105 }
1106 Ok(bits.finish())
1107}
1108
1109fn sorted(keys: &[Option<i128>], base: i128, rows: u64) -> Result<(Body, bool)> {
1115 let mut pairs: Vec<(u64, u64)> = Vec::with_capacity(keys.len());
1116 for (rid, key) in keys.iter().enumerate() {
1117 let Some(key) = *key else { continue };
1118 let offset = offset_of(key, base)?;
1119 let rid = u64::try_from(rid).map_err(|_| malformed("the column is too long for a rid"))?;
1120 pairs.push((offset, rid));
1121 }
1122 pairs.sort_unstable();
1127 let distinct = pairs.windows(2).all(|pair| pair[0].0 != pair[1].0);
1128 debug_assert_eq!(
1129 u64::try_from(pairs.len()).ok(),
1130 Some(rows),
1131 "the pair list is the non-null column"
1132 );
1133 let key_width = width_for(pairs.last().map_or(0, |pair| pair.0));
1134 let rows_width = u64::try_from(keys.len().saturating_sub(1))
1135 .map_err(|_| malformed("the column is too long for a rid"))?;
1136 let rid_width = width_for(rows_width);
1137 let mut key_bytes = Vec::new();
1138 let mut rid_bytes = Vec::new();
1139 let key_values: Vec<u64> = pairs.iter().map(|pair| pair.0).collect();
1140 let rid_values: Vec<u64> = pairs.iter().map(|pair| pair.1).collect();
1141 bitpack::pack_linear(&key_values, key_width, &mut key_bytes)?;
1144 bitpack::pack_linear(&rid_values, rid_width, &mut rid_bytes)?;
1145 Ok((
1146 Body::Sorted { base, key_width, keys: key_bytes, rid_width, perm: rid_bytes, count: rows },
1147 distinct,
1148 ))
1149}
1150
1151fn width_for(largest: u64) -> usize {
1157 let bits = u64::BITS - largest.leading_zeros();
1158 bits.max(1) as usize
1159}
1160
1161fn malformed(message: impl Into<String>) -> Error {
1162 Error::invalid_input(format!("invalid rudb key map: {}", message.into()))
1163}
1164
1165#[cfg(test)]
1166mod tests {
1167 use super::*;
1168
1169 fn keys(values: &[i128]) -> Vec<Option<i128>> {
1170 values.iter().copied().map(Some).collect()
1171 }
1172
1173 fn resolves(column: &[Option<i128>], map: &KeyMap) {
1175 for (rid, key) in column.iter().enumerate() {
1176 let Some(key) = *key else { continue };
1177 let found = map.lookup(key).expect("lookup").expect("a key in the column resolves");
1178 assert_eq!(found, rid as u64, "key {key} resolved to {found} rather than {rid}");
1179 }
1180 }
1181
1182 #[test]
1183 fn a_sequence_from_one_is_the_identity_form_and_stores_two_numbers() {
1184 let column = keys(&(1..=1000).collect::<Vec<i128>>());
1187 let map = KeyMap::build(&column).expect("build");
1188 assert_eq!(map.form(), Form::Identity);
1189 assert_eq!(map.bytes(), 24, "section 4.2 says identity is twenty four bytes");
1190 assert_eq!(map.len(), 1000);
1191 resolves(&column, &map);
1192 assert_eq!(map.lookup(0).expect("lookup"), None, "below the base");
1193 assert_eq!(map.lookup(1001).expect("lookup"), None, "past the end");
1194 assert_eq!(map.span(), Some((1, 1000)));
1195 }
1196
1197 #[test]
1198 fn the_rows_of_a_span_are_the_rows_a_lookup_of_each_key_finds() {
1199 let identity = keys(&(5..1005).collect::<Vec<i128>>());
1200 let dense = keys(&(0..3000).filter(|value| value % 3 != 1).collect::<Vec<i128>>());
1201 let mut shuffled = (0..3000).filter(|value| value % 3 != 1).collect::<Vec<i128>>();
1202 shuffled.sort_by_key(|value| (value * 7919) % 3001);
1203 let permuted = keys(&shuffled);
1204 for (column, form) in
1205 [(identity, Form::Identity), (dense, Form::Dense), (permuted, Form::Permuted)]
1206 {
1207 let map = KeyMap::build(&column).expect("build");
1208 assert_eq!(map.form(), form);
1209 let rows = column.len() as u64;
1210 let (base, range) = map.span().expect("a span");
1211 let mut held = vec![0_u64; (range / 64 + 1) as usize];
1212 let mut wanted = vec![0_u64; rows.div_ceil(64) as usize];
1213 for key in column.iter().flatten().filter(|key| *key % 5 == 0 || *key % 7 == 3) {
1214 let offset = (key - base) as u64;
1215 held[(offset / 64) as usize] |= 1 << (offset % 64);
1216 let rid = map.lookup(*key).expect("lookup").expect("a key in the column");
1217 wanted[(rid / 64) as usize] |= 1 << (rid % 64);
1218 }
1219 assert_eq!(map.rows_of_span(&held, rows).expect("rows"), Some(wanted), "{form:?}");
1220 if form != Form::Identity {
1221 let missing = (0..range).find(|offset| {
1223 map.lookup(base + i128::from(*offset)).expect("lookup").is_none()
1224 });
1225 let offset = missing.expect("a hole in the span");
1226 held[(offset / 64) as usize] |= 1 << (offset % 64);
1227 assert_eq!(map.rows_of_span(&held, rows).expect("rows"), None, "{form:?}");
1228 }
1229 let last = held.len() - 1;
1230 held[last] |= 1 << 63;
1231 assert_eq!(map.rows_of_span(&held, rows).expect("rows"), None, "past the span");
1232 }
1233 let sorted = keys(&(0..1000).map(|value| value * 1000).collect::<Vec<i128>>());
1234 let map = KeyMap::build(&sorted).expect("build");
1235 assert_eq!(map.rows_of_span(&[0; 4], 1000).expect("rows"), None, "no span");
1236 }
1237
1238 #[test]
1239 fn a_sequence_from_zero_is_also_the_identity_form() {
1240 let column = keys(&(0..64).collect::<Vec<i128>>());
1241 let map = KeyMap::build(&column).expect("build");
1242 assert_eq!(map.form(), Form::Identity);
1243 resolves(&column, &map);
1244 }
1245
1246 #[test]
1247 fn a_sequence_with_a_gap_in_it_is_the_dense_form() {
1248 let column = keys(&(0..1000).map(|value| value * 2).collect::<Vec<i128>>());
1251 let map = KeyMap::build(&column).expect("build");
1252 assert_eq!(map.form(), Form::Dense);
1253 resolves(&column, &map);
1254 assert_eq!(
1255 map.lookup(1).expect("lookup"),
1256 None,
1257 "a value in the range and not in the column"
1258 );
1259 assert_eq!(map.lookup(2001).expect("lookup"), None, "past the range");
1260 assert_eq!(map.span(), Some((0, 1999)), "from the smallest key to the largest");
1261 }
1262
1263 #[test]
1264 fn a_range_too_sparse_for_a_bitmap_is_the_sorted_form() {
1265 let column = keys(&(0..1000).map(|value| value * 1000).collect::<Vec<i128>>());
1268 let map = KeyMap::build(&column).expect("build");
1269 assert_eq!(map.form(), Form::Sorted);
1270 resolves(&column, &map);
1271 assert_eq!(map.lookup(500).expect("lookup"), None);
1272 assert_eq!(map.span(), None, "too sparse for a bitmap over the range");
1273 }
1274
1275 #[test]
1276 fn the_sorted_form_is_not_bounded_by_a_packed_unit() {
1277 let column = keys(&(0..5000).map(|value| (value * 7919) % 100_003).collect::<Vec<i128>>());
1283 let map = KeyMap::build(&column).expect("build");
1284 assert_eq!(map.form(), Form::Sorted);
1285 resolves(&column, &map);
1286 }
1287
1288 #[test]
1289 fn keys_in_no_order_at_all_resolve_to_the_rows_that_hold_them() {
1290 let column = keys(&[500, 3, 9000, 12, 7, 88, 41, 6]);
1294 let map = KeyMap::build(&column).expect("build");
1295 assert_eq!(map.form(), Form::Sorted);
1296 resolves(&column, &map);
1297 }
1298
1299 #[test]
1300 fn a_descending_column_dense_enough_for_a_bitmap_still_resolves_correctly() {
1301 let column = keys(&(0..500).rev().collect::<Vec<i128>>());
1304 let map = KeyMap::build(&column).expect("build");
1305 assert_eq!(map.form(), Form::Permuted, "a descending column cannot take the bare bitmap");
1306 resolves(&column, &map);
1307 }
1308
1309 #[test]
1310 fn nulls_are_not_keys_and_do_not_shift_the_rows_around_them() {
1311 let column = vec![Some(10), None, Some(20), None, Some(30)];
1317 let map = KeyMap::build(&column).expect("build");
1318 assert_eq!(
1319 map.form(),
1320 Form::Permuted,
1321 "a null before a key shifts it out of the positional forms"
1322 );
1323 resolves(&column, &map);
1324 assert_eq!(map.observed().nulls, 2);
1325 assert_eq!(map.observed().rows, 3);
1326 assert_eq!(
1327 map.lookup(20).expect("lookup"),
1328 Some(2),
1329 "the rid is the position in the column"
1330 );
1331 }
1332
1333 #[test]
1334 fn a_leading_null_keeps_an_otherwise_perfect_sequence_out_of_the_identity_form() {
1335 let mut column = vec![None];
1339 column.extend((1..=1000).map(Some));
1340 let map = KeyMap::build(&column).expect("build");
1341 assert_ne!(map.form(), Form::Identity);
1342 resolves(&column, &map);
1343 assert_eq!(map.lookup(1).expect("lookup"), Some(1), "row zero is the null, not key one");
1344 }
1345
1346 #[test]
1347 fn a_null_only_column_builds_and_resolves_nothing() {
1348 let column = vec![None, None, None];
1349 let map = KeyMap::build(&column).expect("build");
1350 assert!(map.is_empty());
1351 assert_eq!(map.observed().nulls, 3);
1352 assert_eq!(map.lookup(0).expect("lookup"), None);
1353 }
1354
1355 #[test]
1356 fn an_empty_column_builds_and_resolves_nothing() {
1357 let map = KeyMap::build(&[]).expect("build");
1358 assert!(map.is_empty());
1359 assert_eq!(map.lookup(0).expect("lookup"), None);
1360 assert!(map.observed().usable_as_parent(), "an empty parent is unique, vacuously");
1361 }
1362
1363 #[test]
1364 fn a_duplicated_key_is_reported_rather_than_resolved_to_one_of_its_rows() {
1365 let column = keys(&[5, 7, 5, 9]);
1368 let map = KeyMap::build(&column).expect("build");
1369 assert!(!map.observed().distinct);
1370 assert!(!map.observed().usable_as_parent(), "a non-unique parent side takes no link");
1371 }
1372
1373 #[test]
1374 fn a_column_that_arrives_with_its_repeats_together_is_not_sorted_into_a_map() {
1375 let column = keys(&[1, 1, 2, 2, 2, 90_000, 90_000]);
1379 let map = KeyMap::build_from(&column[..]).expect("build");
1380 assert!(!map.observed().distinct);
1381 assert_eq!(map.observed().rows, 7, "the column was still counted");
1382 assert_eq!(map.observed().max, Some(90_000));
1383 assert_eq!(map.bytes(), KeyMap::build(&keys(&[])).expect("build").bytes());
1384 assert_eq!(map.lookup(2).expect("lookup"), None, "and it answers nothing, as it must");
1385 }
1386
1387 #[test]
1388 fn a_single_key_column_resolves_it() {
1389 let column = keys(&[42]);
1392 let map = KeyMap::build(&column).expect("build");
1393 resolves(&column, &map);
1394 assert_eq!(map.lookup(41).expect("lookup"), None);
1395 assert_eq!(map.lookup(43).expect("lookup"), None);
1396 }
1397
1398 #[test]
1399 fn negative_keys_resolve_because_the_base_is_the_minimum_and_not_zero() {
1400 let column = keys(&[-9000, -3, -1, 0, 7]);
1401 let map = KeyMap::build(&column).expect("build");
1402 resolves(&column, &map);
1403 assert_eq!(map.lookup(-9001).expect("lookup"), None);
1404 }
1405
1406 #[test]
1407 fn a_column_spanning_more_than_a_u64_of_values_is_refused_and_not_panicked_over() {
1408 let column = keys(&[i128::MIN, 0, i128::MAX]);
1412 let error = KeyMap::build(&column).expect_err("refused");
1413 assert!(error.to_string().contains("spans more than a u64"), "{error}");
1414 }
1415
1416 #[test]
1417 fn keys_at_the_far_end_of_the_integer_type_resolve_when_their_range_is_narrow() {
1418 let column = keys(&[i128::MIN, i128::MIN + 5, i128::MIN + 2]);
1421 let map = KeyMap::build(&column).expect("build");
1422 resolves(&column, &map);
1423 assert_eq!(map.lookup(i128::MAX).expect("lookup"), None);
1424 assert_eq!(map.lookup(0).expect("lookup"), None);
1425 }
1426
1427 #[test]
1428 fn the_rank_index_agrees_with_counting_the_bits_by_hand() {
1429 let column = keys(&(0..10_000).map(|value| value * 2).collect::<Vec<i128>>());
1434 let map = KeyMap::build(&column).expect("build");
1435 assert_eq!(map.form(), Form::Dense);
1436 resolves(&column, &map);
1437 }
1438
1439 #[test]
1440 fn a_string_key_arrives_as_dictionary_codes_and_never_as_text() {
1441 let codes = keys(&[7, 1, 4, 9, 2]);
1446 let map = KeyMap::build(&codes).expect("build");
1447 resolves(&codes, &map);
1448 }
1449
1450 #[test]
1451 fn the_form_tag_round_trips_and_an_unknown_one_is_refused() {
1452 for form in [Form::Identity, Form::Dense, Form::Sorted, Form::Permuted] {
1453 assert_eq!(Form::from_tag(form.tag()).expect("a known tag"), form);
1454 }
1455 assert!(Form::from_tag(4).is_err(), "an unfamiliar form is refused rather than guessed");
1456 }
1457
1458 #[test]
1459 fn the_dense_form_costs_a_bitmap_and_about_an_eighth_again() {
1460 let column = keys(&(0..10_000).map(|value| value * 8).collect::<Vec<i128>>());
1463 let map = KeyMap::build(&column).expect("build");
1464 assert_eq!(map.form(), Form::Dense);
1465 let bitmap = 80_000 / 8;
1466 let bytes = map.bytes();
1467 assert!(bytes > bitmap, "the map took {bytes} bytes and the bitmap alone is {bitmap}");
1468 assert!(
1469 bytes < bitmap * 5 / 4,
1470 "the map took {bytes} bytes, more than a quarter over the bitmap's {bitmap}"
1471 );
1472 }
1473
1474 struct Counted {
1476 column: Vec<Option<i128>>,
1477 scans: std::cell::Cell<usize>,
1478 }
1479
1480 impl Keys for Counted {
1481 fn scan(&self, each: &mut dyn FnMut(Option<i128>) -> Result<()>) -> Result<()> {
1482 self.scans.set(self.scans.get() + 1);
1483 self.column.scan(each)
1484 }
1485 }
1486
1487 #[test]
1488 fn a_build_from_a_scan_is_the_same_map_as_a_build_from_a_slice() {
1489 let columns: Vec<Vec<Option<i128>>> = vec![
1493 Vec::new(),
1494 keys(&[]),
1495 keys(&(1..=1000).collect::<Vec<i128>>()),
1496 keys(&(0..500).map(|value| value * 4).collect::<Vec<i128>>()),
1497 keys(&[100, 3, 40, 7, 9000]),
1498 keys(&[5, 5, 9]),
1499 vec![Some(10), None, Some(20), None, Some(30)],
1500 vec![None, None],
1501 shuffled(1_000, 4),
1502 keys(&[1, 3, 2, 1]),
1503 ];
1504 for column in &columns {
1505 let held = KeyMap::build(column).expect("build from a slice");
1506 let read = KeyMap::build_from(&column[..]).expect("build from a scan");
1507 assert_eq!(read.form(), held.form(), "{column:?}");
1508 assert_eq!(read.observed(), held.observed(), "{column:?}");
1509 assert_eq!(read.len(), held.len(), "{column:?}");
1510 assert_eq!(read.bytes(), held.bytes(), "{column:?}");
1511 if read.observed().usable_as_parent() {
1515 resolves(column, &read);
1516 }
1517 }
1518 }
1519
1520 #[test]
1521 fn the_identity_form_is_built_without_reading_the_column_twice() {
1522 let identity =
1526 Counted { column: keys(&(1..=1000).collect::<Vec<i128>>()), scans: 0.into() };
1527 assert_eq!(KeyMap::build_from(&identity).expect("build").form(), Form::Identity);
1528 assert_eq!(
1529 identity.scans.get(),
1530 1,
1531 "the identity form is the observation and nothing more"
1532 );
1533
1534 let dense = Counted {
1537 column: keys(&(0..500).map(|v| v * 4).collect::<Vec<i128>>()),
1538 scans: 0.into(),
1539 };
1540 assert_eq!(KeyMap::build_from(&dense).expect("build").form(), Form::Dense);
1541 assert_eq!(dense.scans.get(), 2);
1542
1543 let sorted = Counted { column: keys(&[100, 3, 40, 7, 9000]), scans: 0.into() };
1544 assert_eq!(KeyMap::build_from(&sorted).expect("build").form(), Form::Sorted);
1545 assert_eq!(sorted.scans.get(), 2);
1546
1547 let permuted = Counted { column: shuffled(1_000, 4), scans: 0.into() };
1550 assert_eq!(KeyMap::build_from(&permuted).expect("build").form(), Form::Permuted);
1551 assert_eq!(permuted.scans.get(), 3);
1552 }
1553
1554 fn shuffled(count: i128, step: i128) -> Vec<Option<i128>> {
1559 (0..count).map(|at| Some((at * 7_919 % count) * step)).collect()
1560 }
1561
1562 #[test]
1563 fn dense_keys_stored_out_of_key_order_take_the_permuted_form() {
1564 let column = shuffled(10_000, 4);
1568 let map = KeyMap::build(&column).expect("build");
1569 assert_eq!(map.form(), Form::Permuted);
1570 assert!(map.observed().distinct);
1571 assert!(!map.observed().sorted);
1572 resolves(&column, &map);
1573 assert_eq!(map.lookup(1).expect("lookup"), None, "a key between two keys is not a key");
1574 assert_eq!(map.lookup(40_000).expect("lookup"), None, "past the end");
1575 assert_eq!(map.span(), Some((0, 39_997)), "the span is about the keys and not the rows");
1576 let sorted = 10_000 * (16 + 14) / 8;
1579 assert!(map.bytes() * 10 < sorted * 7, "{} bytes against {sorted}", map.bytes());
1580 }
1581
1582 #[test]
1583 fn a_repeat_that_is_not_adjacent_keeps_a_dense_column_out_of_every_form() {
1584 let column = keys(&[4, 1, 3, 2, 4]);
1587 let map = KeyMap::build(&column).expect("build");
1588 assert!(!map.observed().distinct);
1589 assert!(!map.observed().usable_as_parent());
1590 assert_eq!(map.lookup(4).expect("lookup"), None);
1591 let read = KeyMap::build_from(&column[..]).expect("build");
1592 assert_eq!(read.observed(), map.observed());
1593 }
1594
1595 #[test]
1596 fn a_scan_that_fails_stops_the_build_rather_than_half_finishing_it() {
1597 struct Broken;
1598 impl Keys for Broken {
1599 fn scan(&self, _: &mut dyn FnMut(Option<i128>) -> Result<()>) -> Result<()> {
1600 Err(malformed("the column could not be read"))
1601 }
1602 }
1603 let error = KeyMap::build_from(&Broken).expect_err("a build over an unreadable column");
1604 assert!(error.to_string().contains("could not be read"), "{error}");
1605 }
1606}