mod resolver;
pub use resolver::ResourceResolver;
mod sqpack;
pub use sqpack::{RepairAction, RepairError, SqPackRelease, SqPackResource};
mod unpacked;
pub use unpacked::UnpackedResource;
use crate::{
ByteBuffer, Error, ReadableFile,
common::{Language, Platform},
excel::{Page, Sheet},
exd::EXD,
exh::EXH,
exl::EXL,
};
impl Clone for Box<dyn Resource> {
fn clone(&self) -> Box<dyn Resource> {
self.clone_box()
}
}
pub trait ClonableResource {
fn clone_box(&self) -> Box<dyn Resource>;
}
impl<T> ClonableResource for T
where
T: 'static + Resource + Clone,
{
fn clone_box(&self) -> Box<dyn Resource> {
Box::new(self.clone())
}
}
impl Default for ResourceResolver {
fn default() -> Self {
Self::new()
}
}
pub trait Resource: Send + Sync + ClonableResource + 'static {
fn read(&mut self, path: &str) -> Option<ByteBuffer>;
fn exists(&mut self, path: &str) -> bool;
fn platform(&self) -> Platform {
Platform::Win32
}
}
pub fn generic_parsed<R: Resource + ?Sized, F: ReadableFile>(
resource: &mut R,
path: &str,
) -> Result<F, Error> {
if let Some(bytes) = resource.read(path) {
return F::from_existing(resource.platform(), &bytes).ok_or(Error::FileParsingFailed {
path: path.to_string(),
});
}
Err(Error::FileNotFound {
path: path.to_string(),
})
}
pub fn generic_read_excel_sheet_header<R: Resource + ?Sized>(
resource: &mut R,
name: &str,
) -> Result<EXH, Error> {
let new_filename = name.to_lowercase();
let path = format!("exd/{new_filename}.exh");
generic_parsed::<R, EXH>(resource, &path)
}
pub fn generic_read_excel_sheet<R: Resource + ?Sized>(
resource: &mut R,
exh: &EXH,
name: &str,
language: Language,
) -> Result<Sheet, Error> {
let mut pages = Vec::with_capacity(exh.header.page_count as usize);
for page in 0..exh.header.page_count {
let exd = generic_read_excel_exd(resource, name, exh, language, page as usize)?;
pages.push(Page::from_exd(exh, exd));
}
Ok(Sheet {
exh: exh.clone(),
pages,
})
}
pub fn generic_get_all_sheet_names<R: Resource + ?Sized>(
resource: &mut R,
) -> Result<Vec<String>, Error> {
let root_exl = generic_parsed::<R, EXL>(resource, "exd/root.exl")?;
Ok(root_exl
.entries
.iter()
.map(|(row, _)| row.clone())
.collect())
}
fn generic_read_excel_exd<R: Resource + ?Sized>(
resource: &mut R,
name: &str,
exh: &EXH,
language: Language,
page: usize,
) -> Result<EXD, Error> {
let exd_path = format!(
"exd/{}",
EXD::calculate_filename(name, language, &exh.pages[page])
);
generic_parsed::<R, EXD>(resource, &exd_path)
}