ls: add hash table lookup; refactor htv handling

This commit is contained in:
Alain Zscheile 2023-01-08 20:35:27 +01:00
parent 511b32b320
commit 9813001721
2 changed files with 44 additions and 14 deletions

View file

@ -30,6 +30,13 @@ pub struct HashTableIter<'a> {
chains: &'a [u8],
}
#[derive(Clone, Copy, Debug)]
pub struct HashTableValue {
pub typ: u32,
pub lhs: u64,
pub rhs: u64,
}
impl HashTableHeader {
pub fn parse(data: &[u8]) -> Option<Self> {
if data.len() < 20 {
@ -68,6 +75,19 @@ pub fn hash_trf(h: u64, items: usize, div: usize) -> usize {
div * usize::try_from(h % u64::try_from(items / div).unwrap()).unwrap()
}
impl HashTableValue {
pub fn parse(entry: &[u8]) -> Option<Self> {
if entry.len() < 32 {
return None;
}
Some(Self {
typ: u32::from_be_bytes(entry[12..16].try_into().unwrap()),
lhs: u64::from_be_bytes(entry[16..24].try_into().unwrap()),
rhs: u64::from_be_bytes(entry[24..32].try_into().unwrap()),
})
}
}
impl<'a> HashTableRef<'a> {
/// `location` should be the offset where the hash table is present (in units of 16 bytes)
pub fn parse(data: &'a [u8], location: u32) -> Option<Self> {
@ -92,7 +112,7 @@ impl<'a> HashTableRef<'a> {
}
/// NOTE: the key is truncated after the first null byte
pub fn lookup(&self, key: &[u8]) -> Option<(u32, u64, u64)> {
pub fn lookup(&self, key: &[u8]) -> Option<HashTableValue> {
let key = trunc_key_at0(key);
let (h, blmask) = self.settings.translate_key(key);
@ -118,11 +138,7 @@ impl<'a> HashTableRef<'a> {
let e_name = trunc_key_at0(self.strtab.get(e_name_ix..)?);
if e_name == key {
return Some((
u32::from_be_bytes(sel[12..16].try_into().unwrap()),
u64::from_be_bytes(sel[16..24].try_into().unwrap()),
u64::from_be_bytes(sel[24..32].try_into().unwrap()),
));
return HashTableValue::parse(sel);
}
}
@ -143,7 +159,7 @@ impl<'a> HashTableRef<'a> {
}
impl<'a> Iterator for HashTableIter<'a> {
type Item = (u64, &'a [u8], u32, u64, u64);
type Item = (u64, &'a [u8], HashTableValue);
fn next(&mut self) -> Option<Self::Item> {
if self.chains.len() < 32 {
@ -156,9 +172,7 @@ impl<'a> Iterator for HashTableIter<'a> {
Some((
u64::from_be_bytes(i[0..8].try_into().unwrap()),
e_name,
u32::from_be_bytes(i[12..16].try_into().unwrap()),
u64::from_be_bytes(i[16..24].try_into().unwrap()),
u64::from_be_bytes(i[24..32].try_into().unwrap()),
HashTableValue::parse(i).unwrap(),
))
}
}

View file

@ -24,6 +24,9 @@ enum Command {
/// list hash table
Hash,
/// resolve a key via hash table
HashLookup { key: String },
/// list 2D "hilbert curve" table
X2dhc,
}
@ -78,17 +81,30 @@ fn main() {
let ht = yglnk_core::HashTableRef::parse(data, cli.location)
.expect("unable to parse table header");
println!("hash\tL\tR\tname\t\ttyp");
for (hash, name, typ, val_l, val_r) in ht.iter() {
for (hash, name, value) in ht.iter() {
println!(
"{:016x}\t{:016x}\t{:016x}\t{}\t{}",
hash,
val_l,
val_r,
value.lhs,
value.rhs,
name_to_txt(name),
typ_to_txt(typ)
typ_to_txt(value.typ)
);
}
}
Command::HashLookup { key } => {
let ht = yglnk_core::HashTableRef::parse(data, cli.location)
.expect("unable to parse table header");
match ht.lookup(key.as_bytes()) {
None => println!("(none)"),
Some(value) => println!(
"typ={} L={:016x} R={:016x}",
typ_to_txt(value.typ),
value.lhs,
value.rhs
),
}
}
Command::X2dhc => unimplemented!(),
}
}