ls: add hash table lookup; refactor htv handling
This commit is contained in:
parent
511b32b320
commit
9813001721
|
@ -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(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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!(),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue