use anyhow::Context;
use bytes::Bytes;
use oozextract::Extractor;
use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator};
use crate::file_parsers::bundle::types::BundleFile;
impl BundleFile {
pub fn read_all(&self) -> anyhow::Result<Bytes> {
self.read_range(0, self.head.uncompressed_size as usize)
}
pub fn read_range(&self, offset: usize, len: usize) -> anyhow::Result<Bytes> {
let block_size = self.head.uncompressed_block_granularity as usize;
let block_start = offset / block_size;
let block_end = (offset + len).div_ceil(block_size);
let buf_size = (block_end * block_size).min(self.head.uncompressed_size as usize)
- block_start * block_size;
let mut buf = vec![0; buf_size];
let chunks = buf.chunks_mut(block_size).collect::<Vec<_>>();
chunks
.into_par_iter()
.zip(&self.blocks[block_start..block_end])
.try_for_each(|(chunk, block)| {
let mut ext = Extractor::new();
ext.read_from_slice(block, chunk)
.map(|_| ())
.context("Failed to decompress bundle block")
})?;
let slice = Bytes::from(buf).slice(offset % block_size..offset % block_size + len);
Ok(slice)
}
}