use crate::ZeroTrieSimpleAscii;
use zerovec::ule::tuplevar::Tuple3VarULE;
use zerovec::ule::vartuple::VarTuple;
use zerovec::ule::vartuple::VarTupleULE;
use zerovec::ule::EncodeAsVarULE;
use zerovec::vecs::Index32;
use zerovec::ZeroSlice;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
#[cfg(feature = "alloc")]
use zerovec::ZeroVec;
pub(crate) type DenseType = u16;
#[cfg(feature = "alloc")]
#[derive(Debug, PartialEq, Eq)]
pub struct ZeroAsciiDenseSparse2dTrieOwned {
pub(crate) primary: ZeroTrieSimpleAscii<Vec<u8>>,
pub(crate) suffixes: ZeroTrieSimpleAscii<Vec<u8>>,
pub(crate) dense: ZeroVec<'static, DenseType>,
pub(crate) suffix_count: u16,
pub(crate) delimiter: u8,
}
pub type ZeroAsciiDenseSparse2dTrieVarULE = VarTupleULE<
(u16, u8),
Tuple3VarULE<ZeroSlice<u8>, ZeroSlice<u8>, ZeroSlice<DenseType>, Index32>,
>;
#[derive(Debug, PartialEq, Eq)]
pub struct ZeroAsciiDenseSparse2dTrieBorrowed<'a> {
primary: &'a ZeroTrieSimpleAscii<[u8]>,
suffixes: &'a ZeroTrieSimpleAscii<[u8]>,
dense: &'a ZeroSlice<DenseType>,
suffix_count: u16,
delimiter: u8,
}
#[cfg(feature = "alloc")]
impl ZeroAsciiDenseSparse2dTrieOwned {
pub fn as_borrowed(&self) -> ZeroAsciiDenseSparse2dTrieBorrowed<'_> {
ZeroAsciiDenseSparse2dTrieBorrowed {
primary: self.primary.as_borrowed(),
suffixes: self.suffixes.as_borrowed(),
dense: self.dense.as_slice(),
suffix_count: self.suffix_count,
delimiter: self.delimiter,
}
}
}
impl<'a> From<&'a ZeroAsciiDenseSparse2dTrieVarULE> for ZeroAsciiDenseSparse2dTrieBorrowed<'a> {
fn from(ule: &ZeroAsciiDenseSparse2dTrieVarULE) -> ZeroAsciiDenseSparse2dTrieBorrowed<'_> {
ZeroAsciiDenseSparse2dTrieBorrowed {
primary: ZeroTrieSimpleAscii::from_bytes(ule.variable.a().as_ule_slice()),
suffixes: ZeroTrieSimpleAscii::from_bytes(ule.variable.b().as_ule_slice()),
dense: ule.variable.c(),
suffix_count: ule.sized.0.as_unsigned_int(),
delimiter: ule.sized.1,
}
}
}
impl<'a> ZeroAsciiDenseSparse2dTrieBorrowed<'a> {
pub fn get(&self, prefix: &str, suffix: &str) -> Option<usize> {
let mut cursor = self.primary.cursor();
for b in prefix.as_bytes().iter() {
if cursor.is_empty() {
return None;
}
cursor.step(*b);
}
let row_index = cursor.take_value();
cursor.step(self.delimiter);
let row_value_offset = cursor.take_value();
for b in suffix.as_bytes().iter() {
if cursor.is_empty() {
break;
}
cursor.step(*b);
}
if let Some(value) = cursor.take_value() {
return Some(value);
}
let (Some(row_index), Some(row_value_offset)) = (row_index, row_value_offset) else {
return None;
};
let Some(column_index) = self.suffixes.get(suffix) else {
return None;
};
let suffix_count = usize::from(self.suffix_count);
let Some(offset) = row_index
.checked_mul(suffix_count)
.and_then(|v| v.checked_add(column_index))
.and_then(|index| self.dense.get(index))
else {
debug_assert!(
false,
"matrix index out of bounds: row={}, col={}, suffix_count={}",
row_index, column_index, suffix_count
);
return None;
};
if offset == DenseType::MAX {
return None;
}
let Some(result) = usize::from(offset).checked_add(row_value_offset) else {
debug_assert!(
false,
"overflow: offset={}, row_value_offset={}",
offset, row_value_offset
);
return None;
};
Some(result)
}
pub fn as_encodeable(&self) -> impl EncodeAsVarULE<ZeroAsciiDenseSparse2dTrieVarULE> + '_ {
VarTuple {
sized: (self.suffix_count, self.delimiter),
variable: (
self.primary.as_bytes(),
self.suffixes.as_bytes(),
self.dense,
),
}
}
}