epub_builder/
zip_library.rs1use crate::zip::Zip;
6
7use std::fmt;
8use std::io;
9use std::io::Cursor;
10use std::io::Read;
11use std::io::Write;
12use std::path::Path;
13
14use crate::Result;
15use libzip::CompressionMethod;
16use libzip::ZipWriter;
17
18pub struct ZipLibrary {
27 writer: ZipWriter<Cursor<Vec<u8>>>,
28}
29
30impl fmt::Debug for ZipLibrary {
31 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
32 write!(f, "ZipLibrary")
33 }
34}
35
36impl ZipLibrary {
37 pub fn new() -> Result<ZipLibrary> {
41 let mut writer = ZipWriter::new(Cursor::new(vec![]));
42 writer.set_comment(""); writer.start_file(
44 "mimetype",
45 libzip::write::SimpleFileOptions::default().compression_method(CompressionMethod::Stored),
46 )?;
47 writer
48 .write(b"application/epub+zip")
49 .map_err(|e| crate::Error::IoError {
50 msg: "could not write mimetype in epub".to_string(),
51 cause: e,
52 })?;
53
54 Ok(ZipLibrary { writer })
55 }
56}
57
58impl Zip for ZipLibrary {
59 fn write_file<P: AsRef<Path>, R: Read>(&mut self, path: P, mut content: R) -> Result<()> {
60 let mut file = format!("{}", path.as_ref().display());
61 if cfg!(target_os = "windows") {
62 file = file.replace('\\', "/");
64 }
65 let options = libzip::write::SimpleFileOptions::default();
66 self.writer.start_file(file.clone(), options).map_err(|e| {
67 crate::Error::ZipErrorWithMessage {
68 msg: format!("could not create file '{}' in epub", file),
69 cause: e,
70 }
71 })?;
72 io::copy(&mut content, &mut self.writer).map_err(|e| crate::Error::IoError {
73 msg: format!("could not write file '{}' in epub", file),
74 cause: e,
75 })?;
76 Ok(())
77 }
78
79 fn generate<W: Write>(self, mut to: W) -> Result<()> {
80 let cursor = self
81 .writer
82 .finish()
83 .map_err(|e| crate::Error::ZipErrorWithMessage {
84 msg: "error writing zip file".to_string(),
85 cause: e,
86 })?;
87 let bytes = cursor.into_inner();
88 to.write_all(bytes.as_ref())
89 .map_err(|e| crate::Error::IoError {
90 msg: "error writing to file".to_string(),
91 cause: e,
92 })?;
93 Ok(())
94 }
95}