use crate::meta;
use crate::{backend::sdsl_c, interface::common::Ptr};
use anyhow::{format_err, Result};
use crate::interface::common::{self, Code, Id};
use crate::interface::wavelet_trees::layouts;
pub struct WtHuff<
'a,
BitVector = crate::bit_vectors::BitVector,
RankSupport1 = crate::rank_supports::RankSupportV<'a, crate::bit_patterns::P1>,
SelectSupport1 = crate::select_supports::SelectSupportMcl<'a, crate::bit_patterns::P1>,
SelectSupport0 = crate::select_supports::SelectSupportMcl<'a, crate::bit_patterns::P0>,
TreeStrategy = layouts::byte_tree::ByteTree,
> where
BitVector: common::Code,
RankSupport1: common::Code,
SelectSupport1: common::Code,
SelectSupport0: common::Code,
TreeStrategy: layouts::common::TreeStrategy + common::Code,
{
_bs: Option<BitVector>,
_rs1: &'a Option<RankSupport1>,
_ss1: &'a Option<SelectSupport1>,
_ss0: &'a Option<SelectSupport0>,
_ts: Option<TreeStrategy>,
ptr: common::VoidPtr,
interface: Interface<TreeStrategy::Value, TreeStrategy::Size>,
}
impl<'a, BitVector, RankSupport1, SelectSupport1, SelectSupport0, TreeStrategy>
WtHuff<'a, BitVector, RankSupport1, SelectSupport1, SelectSupport0, TreeStrategy>
where
BitVector: common::Code + 'a,
RankSupport1: common::Code,
SelectSupport1: common::Code,
SelectSupport0: common::Code,
TreeStrategy: layouts::common::TreeStrategy + common::Code + 'a,
{
pub fn from_file(path: &std::path::PathBuf) -> Result<Self> {
let path = path
.to_str()
.ok_or(format_err!("Failed to convert PathBuf into str."))?;
let path = std::ffi::CString::new(path)?;
let id = Self::id()?;
let interface = Interface::new(&id)?;
let ptr = (interface.from_file)(path.as_ptr());
let wt = Self::new(interface, ptr)?;
Ok(wt)
}
pub fn from_str(string: &str) -> Result<Self> {
let id = Self::id()?;
let interface = Interface::new(&id)?;
let c_string = std::ffi::CString::new(string)?;
let ptr = (interface.from_string)(c_string.as_ptr());
let wt = Self::new(interface, ptr)?;
Ok(wt)
}
pub fn from_int_vector<const WIDTH: u8>(
int_vector: &crate::interface::int_vector::IntVector<WIDTH>,
) -> Result<Self> {
let id = Self::id()?;
let interface = Interface::new(&id)?;
let ptr = (interface.from_int_vector)(*int_vector.ptr());
let wt = Self::new(interface, ptr)?;
Ok(wt)
}
pub fn from_bit_vector(
bit_vector: &crate::interface::bit_vectors::bit_vector::BitVector,
) -> Result<Self> {
let id = Self::id()?;
let interface = Interface::new(&id)?;
let ptr = (interface.from_bit_vector)(*bit_vector.ptr());
let wt = Self::new(interface, ptr)?;
Ok(wt)
}
fn new(
interface: Interface<TreeStrategy::Value, TreeStrategy::Size>,
ptr: common::VoidPtr,
) -> Result<Self> {
Ok(Self {
_bs: None,
_rs1: &None,
_ss1: &None,
_ss0: &None,
_ts: None,
ptr,
interface,
})
}
pub fn len(&self) -> usize {
(self.interface.len)(self.ptr)
}
pub fn is_empty(&self) -> bool {
(self.interface.is_empty)(self.ptr)
}
pub fn get(&self, index: usize) -> TreeStrategy::Value {
(self.interface.get)(self.ptr, index)
}
pub fn rank(
&self,
index: TreeStrategy::Size,
symbol: TreeStrategy::Value,
) -> TreeStrategy::Size {
(self.interface.rank)(self.ptr, index, symbol)
}
pub fn inverse_select(
&self,
index: TreeStrategy::Size,
) -> (TreeStrategy::Value, TreeStrategy::Size) {
let (rank, symbol) = (self.interface.inverse_select)(self.ptr, index).into();
(symbol, rank)
}
pub fn select(&self, i: TreeStrategy::Size, symbol: TreeStrategy::Value) -> TreeStrategy::Size {
(self.interface.select)(self.ptr, i, symbol)
}
pub fn interval_symbols(
&self,
start_index: TreeStrategy::Size,
end_index: TreeStrategy::Size,
) -> IntervalSymbols<TreeStrategy::Value, TreeStrategy::Size> {
let result = (self.interface.interval_symbols)(self.ptr, start_index, end_index);
IntervalSymbols {
interval_alphabet_size: result.interval_alphabet_size,
interval_symbols: common::array_from_c_array(result.cs, result.length.into()),
rank_symbols_lower: common::array_from_c_array(result.rank_c_i, result.length.into()),
rank_symbols_upper: common::array_from_c_array(result.rank_c_j, result.length.into()),
internal_results: result,
interface: self.interface.clone(),
}
}
pub fn lex_count(
&self,
start_index: TreeStrategy::Size,
end_index: TreeStrategy::Size,
symbol: TreeStrategy::Value,
) -> LexCount {
assert!(
TreeStrategy::LEX_ORDERED,
"TreeStrategy is not lex ordered."
);
(self.interface.lex_count)(self.ptr, start_index, end_index, symbol)
}
pub fn lex_smaller_count(
&self,
index: TreeStrategy::Size,
symbol: TreeStrategy::Value,
) -> LexSmallerCount {
assert!(
TreeStrategy::LEX_ORDERED,
"TreeStrategy is not lex ordered."
);
(self.interface.lex_smaller_count)(self.ptr, index, symbol)
}
pub fn symbol_gte(&self, symbol: TreeStrategy::Value) -> Option<TreeStrategy::Value> {
let result = (self.interface.symbol_gte)(self.ptr, symbol);
if result.found {
Some(result.symbol)
} else {
None
}
}
pub fn symbol_lte(&self, symbol: TreeStrategy::Value) -> Option<TreeStrategy::Value> {
let result = (self.interface.symbol_lte)(self.ptr, symbol);
if result.found {
Some(result.symbol)
} else {
None
}
}
pub fn alphabet_size(&self) -> TreeStrategy::Size {
(self.interface.alphabet_size)(self.ptr)
}
pub fn iter(&self) -> common::VectorIterator<TreeStrategy::Value, Self> {
common::VectorIterator::new(&self, self.len())
}
}
impl<'a, BitVector, RankSupport1, SelectSupport1, SelectSupport0, TreeStrategy> common::io::IO
for WtHuff<'a, BitVector, RankSupport1, SelectSupport1, SelectSupport0, TreeStrategy>
where
BitVector: common::Code,
RankSupport1: common::Code,
SelectSupport1: common::Code,
SelectSupport0: common::Code,
TreeStrategy: layouts::common::TreeStrategy + common::Code,
{
fn io(&self) -> &common::io::Interface {
&self.interface.io
}
}
impl<'a, BitVector, RankSupport1, SelectSupport1, SelectSupport0, TreeStrategy> common::Ptr
for WtHuff<'a, BitVector, RankSupport1, SelectSupport1, SelectSupport0, TreeStrategy>
where
BitVector: common::Code,
RankSupport1: common::Code,
SelectSupport1: common::Code,
SelectSupport0: common::Code,
TreeStrategy: layouts::common::TreeStrategy + common::Code,
{
fn ptr(&self) -> &common::VoidPtr {
&self.ptr
}
}
impl<'a, BitVector, RankSupport1, SelectSupport1, SelectSupport0, TreeStrategy> common::Id
for WtHuff<'a, BitVector, RankSupport1, SelectSupport1, SelectSupport0, TreeStrategy>
where
BitVector: common::Code + 'a,
RankSupport1: common::Code + 'a,
SelectSupport1: common::Code + 'a,
SelectSupport0: common::Code + 'a,
TreeStrategy: layouts::common::TreeStrategy + common::Code + 'a,
{
fn id() -> Result<String> {
let meta = Box::new(meta::wavelet_trees::wt_huff::WtHuffMeta::new())
as Box<dyn meta::common::Meta>;
let parameters_c_code = Self::parameters_c_code()?;
let id = sdsl_c::specification::get_id(&meta.c_code(¶meters_c_code)?)?;
Ok(id)
}
}
impl<'a, BitVector, RankSupport1, SelectSupport1, SelectSupport0, TreeStrategy> common::Code
for WtHuff<'a, BitVector, RankSupport1, SelectSupport1, SelectSupport0, TreeStrategy>
where
BitVector: common::Code,
RankSupport1: common::Code + 'a,
SelectSupport1: common::Code + 'a,
SelectSupport0: common::Code + 'a,
TreeStrategy: layouts::common::TreeStrategy + common::Code,
{
fn c_code() -> Result<String> {
let meta = Box::new(meta::wavelet_trees::wt_huff::WtHuffMeta::new())
as Box<dyn meta::common::Meta>;
let parameters_c_code = Self::parameters_c_code()?;
Ok(meta.c_code(¶meters_c_code)?)
}
fn parameters_c_code() -> Result<Vec<String>> {
Ok(vec![
BitVector::c_code()?,
RankSupport1::c_code()?,
SelectSupport1::c_code()?,
SelectSupport0::c_code()?,
TreeStrategy::c_code()?,
])
}
}
impl<'a, BitVector, RankSupport1, SelectSupport1, SelectSupport0, TreeStrategy>
common::IterGet<TreeStrategy::Value>
for WtHuff<'a, BitVector, RankSupport1, SelectSupport1, SelectSupport0, TreeStrategy>
where
BitVector: common::Code,
RankSupport1: common::Code,
SelectSupport1: common::Code,
SelectSupport0: common::Code,
TreeStrategy: layouts::common::TreeStrategy + common::Code,
{
fn iter_get(&self, index: usize) -> TreeStrategy::Value {
(self.interface.get)(self.ptr, index)
}
}
impl<'a, BitVector, RankSupport1, SelectSupport1, SelectSupport0, TreeStrategy> Drop
for WtHuff<'a, BitVector, RankSupport1, SelectSupport1, SelectSupport0, TreeStrategy>
where
BitVector: common::Code,
RankSupport1: common::Code,
SelectSupport1: common::Code,
SelectSupport0: common::Code,
TreeStrategy: layouts::common::TreeStrategy + common::Code,
{
fn drop(&mut self) {
(self.interface.drop)(self.ptr)
}
}
impl<'a, BitVector, RankSupport1, SelectSupport1, SelectSupport0, TreeStrategy> Clone
for WtHuff<'a, BitVector, RankSupport1, SelectSupport1, SelectSupport0, TreeStrategy>
where
BitVector: common::Code,
RankSupport1: common::Code,
SelectSupport1: common::Code,
SelectSupport0: common::Code,
TreeStrategy: layouts::common::TreeStrategy + common::Code,
{
fn clone(&self) -> Self {
Self {
_bs: None,
_rs1: &None,
_ss1: &None,
_ss0: &None,
_ts: None,
ptr: (self.interface.clone)(self.ptr),
interface: self.interface.clone(),
}
}
}
#[repr(C)]
struct SymbolGte<Value> {
pub found: bool,
pub symbol: Value,
}
#[repr(C)]
struct SymbolLte<Value> {
pub found: bool,
pub symbol: Value,
}
#[repr(C)]
pub struct LexCount {
pub rank: usize,
pub count_smaller_symbols: usize,
pub count_greater_symbols: usize,
}
#[repr(C)]
pub struct LexSmallerCount {
pub rank: usize,
pub count_smaller_symbols: usize,
}
pub struct IntervalSymbols<'a, Value, Size> {
pub interval_alphabet_size: Size,
pub interval_symbols: &'a [Value],
pub rank_symbols_lower: &'a [u64],
pub rank_symbols_upper: &'a [u64],
internal_results: ResultIntervalSymbols<Value, Size>,
interface: Interface<Value, Size>,
}
impl<'a, Value, Size> Drop for IntervalSymbols<'a, Value, Size> {
fn drop(&mut self) {
(self.interface.free_result_interval_symbols)(
self.internal_results.cs,
self.internal_results.rank_c_i,
self.internal_results.rank_c_j,
)
}
}
#[repr(C)]
struct ResultIntervalSymbols<Value, Size> {
interval_alphabet_size: Size,
length: Size,
cs: *const Value,
rank_c_i: *const u64,
rank_c_j: *const u64,
}
#[derive(Clone)]
struct Interface<Value, Size> {
create: extern "C" fn() -> common::VoidPtr,
from_file: extern "C" fn(*const std::os::raw::c_char) -> common::VoidPtr,
from_string: extern "C" fn(*const std::os::raw::c_char) -> common::VoidPtr,
from_int_vector: extern "C" fn(common::VoidPtr) -> common::VoidPtr,
from_bit_vector: extern "C" fn(common::VoidPtr) -> common::VoidPtr,
drop: extern "C" fn(common::VoidPtr),
clone: extern "C" fn(common::VoidPtr) -> common::VoidPtr,
len: extern "C" fn(common::VoidPtr) -> usize,
is_empty: extern "C" fn(common::VoidPtr) -> bool,
get: extern "C" fn(common::VoidPtr, usize) -> Value,
rank: extern "C" fn(common::VoidPtr, Size, Value) -> Size,
inverse_select: extern "C" fn(common::VoidPtr, Size) -> common::Pair<Size, Value>,
select: extern "C" fn(common::VoidPtr, Size, Value) -> Size,
interval_symbols:
extern "C" fn(common::VoidPtr, Size, Size) -> ResultIntervalSymbols<Value, Size>,
free_result_interval_symbols: extern "C" fn(*const Value, *const u64, *const u64),
lex_count: extern "C" fn(common::VoidPtr, Size, Size, Value) -> LexCount,
lex_smaller_count: extern "C" fn(common::VoidPtr, Size, Value) -> LexSmallerCount,
symbol_gte: extern "C" fn(common::VoidPtr, Value) -> SymbolGte<Value>,
symbol_lte: extern "C" fn(common::VoidPtr, Value) -> SymbolLte<Value>,
alphabet_size: extern "C" fn(common::VoidPtr) -> Size,
pub io: common::io::Interface,
_lib: std::sync::Arc<sharedlib::Lib>,
}
impl<Value, Size> Interface<Value, Size> {
pub fn new(id: &str) -> Result<Self> {
let lib = sdsl_c::LIB.clone();
let builder = sdsl_c::FunctionBuilder::new(Some("wt_huff"), id, lib.clone());
Ok(Self {
create: builder.get("create")?,
from_file: builder.get("from_file")?,
from_string: builder.get("from_string")?,
from_int_vector: builder.get("from_int_vector")?,
from_bit_vector: builder.get("from_bit_vector")?,
drop: builder.get("destroy")?,
clone: builder.get("copy")?,
len: builder.get("size")?,
is_empty: builder.get("empty")?,
get: builder.get("get_element")?,
rank: builder.get("rank")?,
inverse_select: builder.get("inverse_select")?,
select: builder.get("select")?,
interval_symbols: builder.get("interval_symbols")?,
free_result_interval_symbols: builder.get("free_result_interval_symbols")?,
lex_count: builder.get("lex_count")?,
lex_smaller_count: builder.get("lex_smaller_count")?,
symbol_gte: builder.get("symbol_gte")?,
symbol_lte: builder.get("symbol_lte")?,
alphabet_size: builder.get("alphabet_size")?,
io: common::io::Interface::new(&id)?,
_lib: lib.clone(),
})
}
}