use crate::decode_from_read_to_roaring;
use crate::headers::file::build_file_header_and_flags;
use crate::headers::file::read_file_header_and_flags;
use crate::headers::block::read_block_header_and_flags;
use crate::encoder::bitmap_encoder::BitmapEncoder;
use crate::compression::BitmapHolder;
use crate::compression::MetadataCompression;
use crate::compression::roaringwrapper::pack_block_roaring;
use std::io::Cursor;
use cxx::CxxString;
use cxx::CxxVector;
use roaring::RoaringBitmap;
use roaring::RoaringTreemap;
#[cxx::bridge(namespace = "ahda")]
mod ffi {
extern "Rust" {
fn encode_file_header_and_flags(
targets: &CxxVector<CxxString>,
name: &CxxString,
n_queries: u32,
) -> Vec<u8>;
fn encode_block32(
queries: &CxxVector<CxxString>,
query_ids: &CxxVector<u32>,
set_bits: &CxxVector<u32>,
) -> Vec<u8>;
fn encode_block64(
queries: &CxxVector<CxxString>,
query_ids: &CxxVector<u32>,
set_bits: &CxxVector<u64>,
) -> Vec<u8>;
fn encode_bitmap(
targets: &CxxVector<CxxString>,
queries: &CxxVector<CxxString>,
name: &CxxString,
set_bits: &CxxVector<u64>,
n_queries: u32,
) -> Vec<u8>;
fn decode_bitmap(
bytes: &CxxVector<u8>,
) -> Vec<u64>;
fn decode_target_names(
bytes: &CxxVector<u8>,
) -> Vec<String>;
pub fn decode_query_ids(
bytes: &CxxVector<u8>,
) -> Vec<u32>;
pub fn decode_query_names(
bytes: &CxxVector<u8>,
) -> Vec<String>;
}
}
pub fn encode_file_header_and_flags(
targets: &CxxVector<CxxString>,
name: &CxxString,
n_queries: u32,
) -> Vec<u8> {
let target_names: Vec<Vec<u8>> = targets.iter().map(|x| x.as_bytes().to_vec()).collect();
let query_name: Vec<u8> = name.as_bytes().to_vec();
let (mut header, flags) = build_file_header_and_flags(&target_names, n_queries.try_into().unwrap(), &query_name, &MetadataCompression::default()).unwrap();
let bytes: Vec<u8> = crate::headers::file::encode_file_header_and_flags(&mut header, &flags).unwrap();
bytes
}
pub fn encode_block32(
queries: &CxxVector<CxxString>,
query_ids: &CxxVector<u32>,
set_bits: &CxxVector<u32>,
) -> Vec<u8> {
let bitmap = BitmapHolder::Roaring32(RoaringBitmap::from_iter(set_bits.iter()));
let query_names: Vec<Vec<u8>> = queries.iter().map(|x| x.as_bytes().to_vec()).collect();
let query_names = if query_names.is_empty() { None } else { Some(query_names) };
let block = pack_block_roaring(query_ids.as_slice(), query_names, bitmap);
block.unwrap()
}
pub fn encode_block64(
queries: &CxxVector<CxxString>,
query_ids: &CxxVector<u32>,
set_bits: &CxxVector<u64>,
) -> Vec<u8> {
let bitmap = BitmapHolder::Roaring64(RoaringTreemap::from_iter(set_bits.iter()));
let query_names: Vec<Vec<u8>> = queries.iter().map(|x| x.as_bytes().to_vec()).collect();
let query_names = if query_names.is_empty() { None } else { Some(query_names) };
let block = pack_block_roaring(query_ids.as_slice(), query_names, bitmap);
block.unwrap()
}
pub fn encode_bitmap(
targets: &CxxVector<CxxString>,
queries: &CxxVector<CxxString>,
name: &CxxString,
set_bits: &CxxVector<u64>,
n_queries: u32,
) -> Vec<u8> {
let query_names: Vec<Vec<u8>> = queries.iter().map(|x| x.as_bytes().to_vec()).collect();
let target_names: Vec<Vec<u8>> = targets.iter().map(|x| x.as_bytes().to_vec()).collect();
let query_name: Vec<u8> = name.as_bytes().to_vec();
let mut set_bits_iter = set_bits.as_slice().iter().cloned();
let mut encoder = BitmapEncoder::new(&mut set_bits_iter, &target_names, &query_name, n_queries as usize).unwrap();
if !query_names.is_empty() {
encoder.set_query_names(&query_names);
}
let mut bytes: Vec<u8> = encoder.encode_file_header_and_flags().unwrap();
for block in encoder {
bytes.extend(block.unwrap());
}
bytes
}
pub fn decode_bitmap(
bytes: &CxxVector<u8>,
) -> Vec<u64> {
let mut cursor = Cursor::new(bytes.as_slice());
let (bitmap, _, _, _) = decode_from_read_to_roaring(&mut cursor).unwrap();
let set_bits: Vec<u64> = bitmap.iter().collect();
set_bits
}
pub fn decode_target_names(
bytes: &CxxVector<u8>,
) -> Vec<String> {
let mut cursor = Cursor::new(bytes.as_slice());
let (header, flags) = read_file_header_and_flags(&mut cursor).unwrap();
assert_eq!(header.n_targets as usize, flags.target_names.len());
flags.target_names.into_iter().map(|x| String::from_utf8(x.to_vec()).unwrap()).collect()
}
pub fn decode_query_names(
bytes: &CxxVector<u8>,
) -> Vec<String> {
let mut cursor = Cursor::new(bytes.as_slice());
let (header, _) = read_file_header_and_flags(&mut cursor).unwrap();
let mut query_names: Vec<String> = Vec::with_capacity(header.n_queries as usize);
while let Ok((header, flags)) = read_block_header_and_flags(&mut cursor) {
assert_eq!(header.num_records as usize, query_names.len());
assert_eq!(flags.query_ids.as_ref().unwrap().len(), query_names.len());
let mut queries_str = flags.queries.unwrap().into_iter().map(|x| String::from_utf8(x.to_vec()).unwrap());
query_names.extend(&mut queries_str);
cursor.set_position(cursor.position() + header.block_len as u64);
}
query_names
}
pub fn decode_query_ids(
bytes: &CxxVector<u8>,
) -> Vec<u32> {
let mut cursor = Cursor::new(bytes.as_slice());
let (header, _) = read_file_header_and_flags(&mut cursor).unwrap();
let mut query_ids: Vec<u32> = Vec::with_capacity(header.n_queries as usize);
while let Ok((header, flags)) = read_block_header_and_flags(&mut cursor) {
assert_eq!(header.num_records as usize, query_ids.len());
assert_eq!(flags.query_ids.as_ref().unwrap().len(), query_ids.len());
query_ids.append(&mut flags.query_ids.unwrap());
cursor.set_position(cursor.position() + header.block_len as u64);
}
query_ids
}