1use std::io::{Write};
2use tokio::io::{AsyncSeek, AsyncWrite};
3
4use super::file::{ZipFile, ZipFileNoData};
5
6const END_OF_CENTRAL_DIR_SIGNATURE: u32 = 0x06054B50;
7
8#[derive(Debug, Default)]
9pub struct ZipData {
10 }
12
13impl ZipData {
14 pub async fn write_with_tokio<W: AsyncWrite + AsyncSeek + Unpin>(
15 &mut self,
16 buf: &mut W,
17 zip_file_iter: &mut tokio::sync::mpsc::Receiver<ZipFile>,
18 ) -> std::io::Result<()> {
19 let mut zip_files = Vec::new();
20 while let Some(zip_file) = zip_file_iter.recv().await {
21 let zip_file_no_data = zip_file.write_local_file_header_with_data_consuming_with_tokio(buf).await?;
22 zip_files.push(zip_file_no_data);
23 }
24
25 let files_amount = super::files_amount_u16(&zip_files);
26
27 let central_dir_offset = super::stream_position_u32_with_tokio(buf).await?;
28
29 self.write_central_dir_with_tokio(zip_files, buf).await?;
30
31 let central_dir_start = super::stream_position_u32_with_tokio(buf).await?;
32
33 self.write_end_of_central_directory_with_tokio(
34 buf,
35 central_dir_offset,
36 central_dir_start,
37 files_amount,
38 ).await
39 }
40
41 async fn write_central_dir_with_tokio<W: AsyncWrite + Unpin, I: IntoIterator<Item=ZipFileNoData>>(
42 &self,
43 zip_files: I,
44 buf: &mut W,
45 ) -> std::io::Result<()> {
46 for zip_file in zip_files {
47 zip_file.write_central_directory_entry_with_tokio(buf).await?;
48 }
49 Ok(())
50 }
51
52 const FOOTER_LENGTH: usize = 22;
53
54 async fn write_end_of_central_directory_with_tokio<W: AsyncWrite + Unpin>(
55 &self,
56 buf: &mut W,
57 central_dir_offset: u32,
58 central_dir_start: u32,
59 files_amount: u16,
60 ) -> std::io::Result<()> {
61 let mut central_dir = [0; Self::FOOTER_LENGTH];
63 {
64 let mut central_dir_buf: &mut [u8] = &mut central_dir;
65
66 central_dir_buf.write_all(&END_OF_CENTRAL_DIR_SIGNATURE.to_le_bytes())?;
68 central_dir_buf.write_all(&0_u16.to_le_bytes())?;
70 central_dir_buf.write_all(&0_u16.to_le_bytes())?;
72 central_dir_buf.write_all(&files_amount.to_le_bytes())?;
74 central_dir_buf.write_all(&files_amount.to_le_bytes())?;
76 central_dir_buf.write_all(&(central_dir_start - central_dir_offset).to_le_bytes())?;
78 central_dir_buf.write_all(¢ral_dir_offset.to_le_bytes())?;
80 central_dir_buf.write_all(&0_u16.to_le_bytes())?;
82 }
83
84 {
85 use tokio::io::AsyncWriteExt;
86 buf.write_all(¢ral_dir).await?;
87 }
88
89 Ok(())
90 }
91}