use std::sync::OnceLock;
use miniz_oxide::inflate::{
TINFLStatus,
core::{
DecompressorOxide, decompress, inflate_flags::TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF,
},
};
use serde::de::DeserializeOwned;
pub fn decompress_blob(blob: &[u8]) -> Vec<u8> {
let (len, compressed) = blob.split_at(4);
let len = u32::from_le_bytes(len.try_into().unwrap()) as usize;
let mut data = vec![0u8; len];
let (status, _, written) = decompress(
&mut DecompressorOxide::default(),
compressed,
&mut data,
0,
TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF,
);
assert!(status == TINFLStatus::Done && written == len, "Failed to decompress data");
data
}
pub fn load<T: DeserializeOwned>(compressed: &[u8]) -> T {
postcard::from_bytes(&decompress_blob(compressed)).unwrap()
}
fn read_varint_u64(bytes: &[u8], pos: &mut usize) -> u64 {
let mut result = 0;
let mut shift = 0;
loop {
let byte = bytes[*pos];
*pos += 1;
result |= u64::from(byte & 0x7f) << shift;
if byte & 0x80 == 0 {
return result;
}
shift += 7;
}
}
pub fn read_varint(bytes: &[u8], pos: &mut usize) -> usize {
usize::try_from(read_varint_u64(bytes, pos)).unwrap()
}
pub fn read_zigzag(bytes: &[u8], pos: &mut usize) -> i64 {
let value = read_varint_u64(bytes, pos);
((value >> 1) as i64) ^ -((value & 1) as i64)
}
pub struct LazyData<T> {
compressed: &'static [u8],
cell: OnceLock<T>,
}
impl<T: DeserializeOwned> LazyData<T> {
pub const fn new(compressed: &'static [u8]) -> Self {
Self { compressed, cell: OnceLock::new() }
}
pub fn get(&self) -> &T {
self.cell.get_or_init(|| load(self.compressed))
}
}
pub struct LazyBlob {
compressed: &'static [u8],
cell: OnceLock<Vec<u8>>,
}
impl LazyBlob {
pub const fn new(compressed: &'static [u8]) -> Self {
Self { compressed, cell: OnceLock::new() }
}
pub fn get(&self) -> &[u8] {
self.cell.get_or_init(|| decompress_blob(self.compressed))
}
}