epub_builder/
zip_library.rsuse crate::zip::Zip;
use std::fmt;
use std::io;
use std::io::Cursor;
use std::io::Read;
use std::io::Write;
use std::path::Path;
use crate::Result;
use libzip::CompressionMethod;
use libzip::ZipWriter;
pub struct ZipLibrary {
writer: ZipWriter<Cursor<Vec<u8>>>,
}
impl fmt::Debug for ZipLibrary {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ZipLibrary")
}
}
impl ZipLibrary {
pub fn new() -> Result<ZipLibrary> {
let mut writer = ZipWriter::new(Cursor::new(vec![]));
writer.set_comment(""); writer.start_file(
"mimetype",
libzip::write::SimpleFileOptions::default().compression_method(CompressionMethod::Stored),
)?;
writer
.write(b"application/epub+zip")
.map_err(|e| crate::Error::IoError {
msg: "could not write mimetype in epub".to_string(),
cause: e,
})?;
Ok(ZipLibrary { writer })
}
}
impl Zip for ZipLibrary {
fn write_file<P: AsRef<Path>, R: Read>(&mut self, path: P, mut content: R) -> Result<()> {
let mut file = format!("{}", path.as_ref().display());
if cfg!(target_os = "windows") {
file = file.replace('\\', "/");
}
let options = libzip::write::SimpleFileOptions::default();
self.writer.start_file(file.clone(), options).map_err(|e| {
crate::Error::ZipErrorWithMessage {
msg: format!("could not create file '{}' in epub", file),
cause: e,
}
})?;
io::copy(&mut content, &mut self.writer).map_err(|e| crate::Error::IoError {
msg: format!("could not write file '{}' in epub", file),
cause: e,
})?;
Ok(())
}
fn generate<W: Write>(self, mut to: W) -> Result<()> {
let cursor = self
.writer
.finish()
.map_err(|e| crate::Error::ZipErrorWithMessage {
msg: "error writing zip file".to_string(),
cause: e,
})?;
let bytes = cursor.into_inner();
to.write_all(bytes.as_ref())
.map_err(|e| crate::Error::IoError {
msg: "error writing to file".to_string(),
cause: e,
})?;
Ok(())
}
}