use super::{Dictionary, DictionaryView};
use crate::core::types::{MAX_TOKEN_SIZE, Token};
#[derive(Default, Debug, Clone)]
pub struct WideDictionary {
data: Vec<u8>,
lens: Vec<u8>,
}
impl WideDictionary {
#[inline]
pub fn num_tokens(&self) -> usize {
self.lens.len()
}
#[inline]
pub(crate) fn from_raw(data: Vec<u8>, lens: Vec<u8>) -> Self {
Self { data, lens }
}
}
impl Dictionary for WideDictionary {
type View<'a> = WideDictionaryView<'a>;
#[inline]
fn as_view(&self) -> WideDictionaryView<'_> {
WideDictionaryView {
data: &self.data,
lens: &self.lens,
}
}
}
#[derive(Copy, Clone, Debug)]
pub struct WideDictionaryView<'a> {
data: &'a [u8],
lens: &'a [u8],
}
impl DictionaryView for WideDictionaryView<'_> {
#[inline]
fn num_tokens(&self) -> usize {
self.lens.len()
}
#[inline]
fn token(&self, id: Token) -> &[u8] {
let row = id as usize * MAX_TOKEN_SIZE;
&self.data[row..row + self.lens[id as usize] as usize]
}
#[inline]
fn token_len(&self, id: Token) -> usize {
self.lens[id as usize] as usize
}
#[inline]
unsafe fn token_ptr(&self, id: Token) -> *const u8 {
unsafe { self.data.as_ptr().add(id as usize * MAX_TOKEN_SIZE) }
}
#[inline]
unsafe fn token_len_unchecked(&self, id: Token) -> usize {
unsafe { *self.lens.get_unchecked(id as usize) as usize }
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::core::dictionary::{CompactDictionary, pad_raw};
fn padded_compact(tokens: &[&[u8]]) -> CompactDictionary {
let mut bytes = Vec::new();
let mut offsets = vec![0u32];
for t in tokens {
bytes.extend_from_slice(t);
offsets.push(bytes.len() as u32);
}
pad_raw(&mut bytes, &offsets);
CompactDictionary::from_raw(bytes, offsets)
}
#[test]
fn num_tokens_counts_rows() {
let wide = padded_compact(&[b"a", b"bc", b"def"]).to_wide();
assert_eq!(wide.num_tokens(), 3);
assert_eq!(wide.as_view().num_tokens(), 3);
}
#[test]
fn to_wide_rows_and_lens_match_tokens() {
let tokens: &[&[u8]] = &[b"a", b"bc", b"def", b"ghij"];
let wide = padded_compact(tokens).to_wide();
assert_eq!(wide.num_tokens(), tokens.len());
for (id, tok) in tokens.iter().enumerate() {
assert_eq!(wide.lens[id] as usize, tok.len());
assert_eq!(
&wide.data[id * MAX_TOKEN_SIZE..id * MAX_TOKEN_SIZE + tok.len()],
*tok
);
}
}
}