use std::fmt::Debug;
use crate::{
error::{Error, ErrorValue, Result},
sqpack,
utility::{HashMapCache, HashMapCacheExt},
Resource,
};
use super::{file, index::Index};
#[derive(Debug)]
pub struct SqPack<R> {
resource: R,
indexes: HashMapCache<(u8, u8), Index>,
}
impl<R: sqpack::Resource> SqPack<R> {
pub fn new(resource: R) -> Self {
Self {
resource,
indexes: Default::default(),
}
}
pub fn version(&self, path: &str) -> Result<String> {
let (repository, _) = self.path_metadata(&path.to_lowercase())?;
self.resource.version(repository)
}
pub fn file(&self, path: &str) -> Result<Vec<u8>> {
let path = path.to_lowercase();
let (repository, category) = self.path_metadata(&path)?;
let location = self
.indexes
.try_get_or_insert((repository, category), || {
Index::new(repository, category, &self.resource)
})?
.find(&path)?;
let dat = self
.resource
.dat(repository, category, location.chunk, location.data_file)?;
file::read(dat, location.offset)
}
fn path_metadata(&self, path: &str) -> Result<(u8, u8)> {
self.resource
.path_metadata(path)
.ok_or_else(|| Error::NotFound(ErrorValue::Path(path.to_string())))
}
}
impl<R> Resource for SqPack<R>
where
R: sqpack::Resource + Send + Sync + 'static,
{
fn version(&self, path: &str) -> Result<String> {
self.version(path)
}
fn file(&self, path: &str) -> Result<Vec<u8>> {
self.file(path)
}
}