use crate::error::Error;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use zip::ZipArchive;
pub struct Archive {
inner: ZipArchive<File>,
}
impl Archive {
pub fn open(path: &Path) -> Result<Self, Error> {
let file = File::open(path)?;
let inner =
ZipArchive::new(file).map_err(|e| Error::Container(format!("zip open: {e}")))?;
Ok(Archive { inner })
}
pub fn read_entry(&mut self, name: &str) -> Result<Vec<u8>, Error> {
let mut entry = self
.inner
.by_name(name)
.map_err(|e| Error::MissingStream(format!("{name}: {e}")))?;
let mut buf = Vec::with_capacity(entry.size() as usize);
entry.read_to_end(&mut buf)?;
Ok(buf)
}
pub fn has_entry(&self, name: &str) -> bool {
self.inner.file_names().any(|n| n == name)
}
pub fn entry_size(&mut self, name: &str) -> Option<u64> {
self.inner.by_name(name).ok().map(|e| e.size())
}
pub fn list_entries(&self) -> Vec<String> {
self.inner.file_names().map(|s| s.to_string()).collect()
}
pub fn validate_mimetype(&mut self) -> Result<(), Error> {
let bytes = self.read_entry("mimetype")?;
let s = std::str::from_utf8(&bytes)
.map_err(|e| Error::Container(format!("mimetype not utf8: {e}")))?
.trim();
if s != "application/hwp+zip" {
return Err(Error::InvalidHeader(format!(
"unexpected HWPX mimetype: {s:?}"
)));
}
Ok(())
}
}