Skip to content

Commit f6f4c21

Browse files
committed
sorting + cleanup
1 parent dbbc00e commit f6f4c21

5 files changed

Lines changed: 352 additions & 119 deletions

File tree

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
use super::group::Group;
2+
use super::group_ops::{CTRL_EMPTY, GROUP_SIZE};
3+
4+
/// Core storage for a hash-sorted map. Owns the group array and supports
5+
/// iteration and drop. Does not contain a hasher — use [`HashSortedMap`]
6+
/// for insertion and lookup.
7+
pub struct HashSortedContainer<K, V> {
8+
pub(crate) groups: Box<[Group<K, V>]>,
9+
pub(crate) num_groups: u32,
10+
pub(crate) n_bits: u32,
11+
pub(crate) len: usize,
12+
}
13+
14+
impl<K, V> HashSortedContainer<K, V> {
15+
pub(crate) fn alloc_groups(n_bits: u32) -> (Box<[Group<K, V>]>, u32) {
16+
let num_primary = 1usize << n_bits;
17+
let total = num_primary + num_primary / 8 + 1;
18+
let mut groups: Vec<Group<K, V>> = Vec::with_capacity(total);
19+
groups.resize_with(total, Group::new);
20+
(groups.into_boxed_slice(), num_primary as u32)
21+
}
22+
23+
pub(crate) fn new(n_bits: u32) -> Self {
24+
let (groups, num_primary) = Self::alloc_groups(n_bits);
25+
Self {
26+
groups,
27+
num_groups: num_primary,
28+
n_bits,
29+
len: 0,
30+
}
31+
}
32+
33+
#[inline]
34+
pub(crate) fn group_index(&self, hash: u64) -> usize {
35+
(hash >> (64 - self.n_bits)) as usize
36+
}
37+
38+
pub fn len(&self) -> usize {
39+
self.len
40+
}
41+
42+
pub fn is_empty(&self) -> bool {
43+
self.len == 0
44+
}
45+
}
46+
47+
impl<K, V> Drop for HashSortedContainer<K, V> {
48+
fn drop(&mut self) {
49+
for group in &mut self.groups[..self.num_groups as usize] {
50+
for i in 0..GROUP_SIZE {
51+
if group.ctrl[i] != CTRL_EMPTY {
52+
unsafe { group.keys[i].assume_init_drop() };
53+
unsafe { group.values[i].assume_init_drop() };
54+
}
55+
}
56+
}
57+
}
58+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use core::mem::MaybeUninit;
2+
3+
use super::group_ops::{CTRL_EMPTY, GROUP_SIZE};
4+
5+
pub(crate) const NO_OVERFLOW: u32 = u32::MAX;
6+
7+
pub(crate) struct Group<K, V> {
8+
pub(crate) ctrl: [u8; GROUP_SIZE],
9+
pub(crate) keys: [MaybeUninit<K>; GROUP_SIZE],
10+
pub(crate) values: [MaybeUninit<V>; GROUP_SIZE],
11+
pub(crate) overflow: u32,
12+
}
13+
14+
impl<K, V> Group<K, V> {
15+
pub(crate) fn new() -> Self {
16+
Self {
17+
ctrl: [CTRL_EMPTY; GROUP_SIZE],
18+
keys: [const { MaybeUninit::uninit() }; GROUP_SIZE],
19+
values: [const { MaybeUninit::uninit() }; GROUP_SIZE],
20+
overflow: NO_OVERFLOW,
21+
}
22+
}
23+
}

0 commit comments

Comments
 (0)