1use std::io::{self, Write, Seek};
2use zip::{ZipWriter, write::SimpleFileOptions, CompressionMethod};
3
4pub struct ZipDocumentWriter<W: Write + Seek> {
6 pub(crate) zip: ZipWriter<W>,
7 pub(crate) manifest: serde_json::Value,
8}
9
10impl<W: Write + Seek> ZipDocumentWriter<W> {
11 pub fn new(w: W) -> io::Result<Self> {
13 let zip = ZipWriter::new(w);
14 let manifest = serde_json::json!({ "version": 1, "entries": [] });
15 Ok(Self { zip, manifest })
16 }
17 pub fn manifest(&self) -> &serde_json::Value {
19 &self.manifest
20 }
21 pub fn manifest_mut(&mut self) -> &mut serde_json::Value {
23 &mut self.manifest
24 }
25 pub fn set_manifest(
27 &mut self,
28 manifest: serde_json::Value,
29 ) -> &mut Self {
30 self.manifest = manifest;
31 self
32 }
33 pub fn add_json(
35 &mut self,
36 name: &str,
37 value: &serde_json::Value,
38 ) -> io::Result<()> {
39 let opts = SimpleFileOptions::default()
40 .compression_method(CompressionMethod::Deflated);
41 self.zip.start_file(name, opts)?;
42 let data = serde_json::to_vec(value)
43 .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
44 if let Some(entries) =
46 self.manifest.get_mut("entries").and_then(|v| v.as_array_mut())
47 {
48 entries.push(serde_json::json!({
49 "name": name,
50 "kind": "json",
51 "logical_len": data.len(),
52 "compression": "deflate"
53 }));
54 }
55 self.zip.write_all(&data)
56 }
57 pub fn add_stored(
59 &mut self,
60 name: &str,
61 bytes: &[u8],
62 ) -> io::Result<()> {
63 let opts = SimpleFileOptions::default()
64 .compression_method(CompressionMethod::Stored);
65 self.zip.start_file(name, opts)?;
66 if let Some(entries) =
67 self.manifest.get_mut("entries").and_then(|v| v.as_array_mut())
68 {
69 entries.push(serde_json::json!({
70 "name": name,
71 "kind": "binary",
72 "logical_len": bytes.len(),
73 "compression": "stored"
74 }));
75 }
76 self.zip.write_all(bytes)
77 }
78 pub fn add_deflated(
80 &mut self,
81 name: &str,
82 bytes: &[u8],
83 ) -> io::Result<()> {
84 let opts = SimpleFileOptions::default()
85 .compression_method(CompressionMethod::Deflated);
86 self.zip.start_file(name, opts)?;
87 if let Some(entries) =
88 self.manifest.get_mut("entries").and_then(|v| v.as_array_mut())
89 {
90 entries.push(serde_json::json!({
91 "name": name,
92 "kind": "binary",
93 "logical_len": bytes.len(),
94 "compression": "deflate"
95 }));
96 }
97 self.zip.write_all(bytes)
98 }
99 pub fn finalize(mut self) -> io::Result<W> {
101 let opts = SimpleFileOptions::default()
102 .compression_method(CompressionMethod::Deflated);
103 self.zip.start_file("manifest.json", opts)?;
104 let data = serde_json::to_vec(&self.manifest)
105 .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
106 self.zip.write_all(&data)?;
107 self.zip.finish().map_err(|e| io::Error::new(io::ErrorKind::Other, e))
108 }
109}