core: simplify and fix hash table iterator

This commit is contained in:
Alain Zscheile 2023-01-13 17:10:28 +01:00
parent d1fabb4804
commit 3758f94b03

View file

@ -29,7 +29,7 @@ pub struct Ref<'a> {
#[derive(Clone)]
pub struct Iter<'a> {
strtab: &'a [u8],
chains: &'a [u8],
chains: core::slice::ChunksExact<'a, u8>,
}
#[derive(Clone, Copy, Debug)]
@ -41,7 +41,7 @@ pub struct Value<R> {
impl Settings {
#[inline]
pub fn chain_entry_size(&self) -> usize {
16 * (1 + usize::from(self.entsize))
(1 + usize::from(self.entsize)).checked_mul(16).unwrap()
}
}
@ -114,6 +114,11 @@ impl<'a> Ref<'a> {
})
}
fn get_e_name<'s>(strtab: &'s [u8], sel: &[u8]) -> Option<&'s [u8]> {
let e_name_ix = usize::try_from(u32::from_be_bytes(sel[8..12].try_into().unwrap())).ok()?;
Some(trunc_key_at0(strtab.get(e_name_ix..)?))
}
/// NOTE: the key is truncated after the first null byte
pub fn lookup(&self, key: &[u8]) -> Option<Value<&'a [u8]>> {
let key = trunc_key_at0(key);
@ -135,15 +140,13 @@ impl<'a> Ref<'a> {
for sel in self
.chains
.chunks(self.settings.chain_entry_size())
.chunks_exact(self.settings.chain_entry_size())
.skip(chain_start)
{
assert!(sel.len() >= 16);
let e_hash = u64::from_be_bytes(sel[0..8].try_into().unwrap());
if (h | 1) == (e_hash | 1) {
let e_name_ix =
usize::try_from(u32::from_be_bytes(sel[8..12].try_into().unwrap())).ok()?;
let e_name = trunc_key_at0(self.strtab.get(e_name_ix..)?);
let e_name = Self::get_e_name(self.strtab, sel)?;
if e_name == key {
return Some(Value::parse(sel).unwrap());
@ -161,7 +164,7 @@ impl<'a> Ref<'a> {
pub fn iter(&self) -> Iter<'a> {
Iter {
strtab: self.strtab,
chains: self.chains,
chains: self.chains.chunks_exact(self.settings.chain_entry_size()),
}
}
}
@ -170,13 +173,8 @@ impl<'a> Iterator for Iter<'a> {
type Item = (u64, &'a [u8], Value<&'a [u8]>);
fn next(&mut self) -> Option<Self::Item> {
if self.chains.len() < 32 {
return None;
}
let (i, j) = self.chains.split_at(32);
self.chains = j;
let e_name_ix = usize::try_from(u32::from_be_bytes(i[8..12].try_into().unwrap())).ok()?;
let e_name = trunc_key_at0(self.strtab.get(e_name_ix..)?);
let i = self.chains.next()?;
let e_name = Ref::get_e_name(self.strtab, i)?;
Some((
u64::from_be_bytes(i[0..8].try_into().unwrap()),
e_name,