mod archive_reader;
mod archive_writer;
pub use archive_reader::ArchiveReader;
pub use archive_writer::ArchiveWriter;
use crate::error::Result;
use crate::types::ArchiveLocation;
use std::borrow::Cow;
use std::path::{Path, PathBuf};
pub struct Archive {
pub id: u16,
pub path: PathBuf,
pub size: u64,
reader: Option<ArchiveReader>,
}
impl Archive {
pub fn new(id: u16, path: PathBuf) -> Result<Self> {
let size = if path.exists() {
std::fs::metadata(&path)?.len()
} else {
0
};
Ok(Self {
id,
path,
size,
reader: None,
})
}
pub fn open(&mut self) -> Result<&mut ArchiveReader> {
if self.reader.is_none() {
self.reader = Some(ArchiveReader::open(&self.path)?);
}
Ok(self.reader.as_mut().unwrap())
}
pub fn read_at_cow(&self, location: &ArchiveLocation) -> Result<Cow<'_, [u8]>> {
if let Some(ref reader) = self.reader {
reader.read_at_cow(location.offset, location.size as usize)
} else {
let mut reader = ArchiveReader::open(&self.path)?;
let data = reader.read_at(location.offset, location.size as usize)?;
Ok(Cow::Owned(data))
}
}
pub fn read_at(&mut self, location: &ArchiveLocation) -> Result<Vec<u8>> {
let reader = self.open()?;
reader.read_at(location.offset, location.size as usize)
}
pub fn contains(&self, location: &ArchiveLocation) -> bool {
location.archive_id == self.id && location.offset + location.size as u64 <= self.size
}
pub fn filename(&self) -> String {
format!("data.{:03}", self.id)
}
pub fn path(&self) -> &Path {
&self.path
}
}