cargo fmt
This commit is contained in:
parent
3d5010806b
commit
ba3326ef24
4 changed files with 116 additions and 74 deletions
87
src/zip.rs
87
src/zip.rs
|
|
@ -5,17 +5,20 @@ use crc32fast::Hasher;
|
|||
use log::debug;
|
||||
use time::OffsetDateTime;
|
||||
|
||||
use crate::UploadedFile;
|
||||
use crate::file::LiveWriter;
|
||||
use crate::UploadedFile;
|
||||
|
||||
const SIGNATURE_SIZE: usize = 4;
|
||||
const SHARED_FIELDS_SIZE: usize = 26;
|
||||
const EXTRA_FIELD_SIZE: usize = 41;
|
||||
const LOCAL_HEADER_SIZE_MINUS_FILENAME: usize = SIGNATURE_SIZE + SHARED_FIELDS_SIZE + EXTRA_FIELD_SIZE;
|
||||
const LOCAL_HEADER_SIZE_MINUS_FILENAME: usize =
|
||||
SIGNATURE_SIZE + SHARED_FIELDS_SIZE + EXTRA_FIELD_SIZE;
|
||||
const DATA_DESCRIPTOR_SIZE: usize = 24;
|
||||
const FILE_ENTRY_SIZE_MINUS_FILENAME_AND_FILE: usize = LOCAL_HEADER_SIZE_MINUS_FILENAME + DATA_DESCRIPTOR_SIZE;
|
||||
const FILE_ENTRY_SIZE_MINUS_FILENAME_AND_FILE: usize =
|
||||
LOCAL_HEADER_SIZE_MINUS_FILENAME + DATA_DESCRIPTOR_SIZE;
|
||||
|
||||
const CENTRAL_DIRECTORY_HEADER_SIZE_MINUS_FILENAME: usize = SIGNATURE_SIZE + 2 + SHARED_FIELDS_SIZE + 14 + EXTRA_FIELD_SIZE;
|
||||
const CENTRAL_DIRECTORY_HEADER_SIZE_MINUS_FILENAME: usize =
|
||||
SIGNATURE_SIZE + 2 + SHARED_FIELDS_SIZE + 14 + EXTRA_FIELD_SIZE;
|
||||
|
||||
const EOCD64_RECORD_SIZE: usize = 56;
|
||||
const EOCD64_LOCATOR_SIZE: usize = 20;
|
||||
|
|
@ -59,7 +62,11 @@ fn fat_timestamp(time: OffsetDateTime) -> u32 {
|
|||
|
||||
/// Append a value to a byte vector as little-endian bytes
|
||||
fn append_value(data: &mut Vec<u8>, mut value: u64, len: usize) {
|
||||
data.resize_with(data.len() + len, || { let byte = value as u8; value >>= 8; byte });
|
||||
data.resize_with(data.len() + len, || {
|
||||
let byte = value as u8;
|
||||
value >>= 8;
|
||||
byte
|
||||
});
|
||||
}
|
||||
|
||||
fn append_repeated_byte(data: &mut Vec<u8>, byte: u8, count: usize) {
|
||||
|
|
@ -80,9 +87,9 @@ impl UploadedFile {
|
|||
/// through "Extra field length".
|
||||
fn shared_header_fields(&self, hash: Option<u32>) -> Vec<u8> {
|
||||
let mut fields = vec![
|
||||
45, 0, // Minimum version required to extract: 4.5 for ZIP64 extensions
|
||||
0b00001000, 0, // General purpose bit flag: size and CRC-32 in data descriptor
|
||||
0, 0, // Compression method: none
|
||||
45, 0, // Minimum version required to extract: 4.5 for ZIP64 extensions
|
||||
0b00001000, 0, // General purpose bit flag: size and CRC-32 in data descriptor
|
||||
0, 0, // Compression method: none
|
||||
];
|
||||
append_value(&mut fields, fat_timestamp(self.modtime) as u64, 4);
|
||||
// Use 0s as a placeholder if the CRC-32 hash isn't known yet
|
||||
|
|
@ -97,8 +104,8 @@ impl UploadedFile {
|
|||
|
||||
fn extra_field(&self, local_header_offset: usize) -> Vec<u8> {
|
||||
let mut field = vec![
|
||||
0x01, 0x00, // Zip64 extended information
|
||||
28, 0, // 28 bytes of data
|
||||
0x01, 0x00, // Zip64 extended information
|
||||
28, 0, // 28 bytes of data
|
||||
];
|
||||
// Original size and compressed size - if this is in the local
|
||||
// header, we're supposed to leave these blank and point to
|
||||
|
|
@ -111,7 +118,7 @@ impl UploadedFile {
|
|||
|
||||
field.append(&mut vec![
|
||||
0x55, 0x54, // Extended timestamp
|
||||
5, 0, // 5 bytes of data
|
||||
5, 0, // 5 bytes of data
|
||||
0b00000001, // Flags: Only modification time is present
|
||||
]);
|
||||
append_value(&mut field, self.modtime.unix_timestamp() as u64, 4);
|
||||
|
|
@ -140,11 +147,12 @@ impl UploadedFile {
|
|||
];
|
||||
header.append(&mut self.shared_header_fields(Some(hash)));
|
||||
header.append(&mut vec![
|
||||
0, 0, // File comment length: 0
|
||||
0, 0, // Disk number where file starts: 0
|
||||
0, 0, // Internal file attributes: nothing
|
||||
0, 0, // File comment length: 0
|
||||
0, 0, // Disk number where file starts: 0
|
||||
0, 0, // Internal file attributes: nothing
|
||||
0, 0, 0, 0, // External file attributes: nothing
|
||||
0xff, 0xff, 0xff, 0xff, // Relative offset of local file header: placeholder, see ZIP64 data
|
||||
0xff, 0xff, 0xff,
|
||||
0xff, // Relative offset of local file header: placeholder, see ZIP64 data
|
||||
]);
|
||||
header.append(&mut self.name.clone().into_bytes());
|
||||
header.append(&mut self.extra_field(local_header_offset));
|
||||
|
|
@ -167,7 +175,7 @@ fn end_of_central_directory(files: &[UploadedFile]) -> Vec<u8> {
|
|||
|
||||
let mut eocd = vec![
|
||||
0x50, 0x4b, 0x06, 0x06, // EOCD64 record signature
|
||||
44, // Size of remaining EOCD64 record
|
||||
44, // Size of remaining EOCD64 record
|
||||
];
|
||||
append_0(&mut eocd, 7); // pad out the rest of the size field
|
||||
eocd.append(&mut vec![
|
||||
|
|
@ -175,7 +183,7 @@ fn end_of_central_directory(files: &[UploadedFile]) -> Vec<u8> {
|
|||
45, 0, // Minimum version 4.5 to extract
|
||||
]);
|
||||
append_0(&mut eocd, 8); // Two 4-byte disk numbers, both 0
|
||||
// Number of central directory records, on this disk and in total
|
||||
// Number of central directory records, on this disk and in total
|
||||
append_value(&mut eocd, files.len() as u64, 8);
|
||||
append_value(&mut eocd, files.len() as u64, 8);
|
||||
append_value(&mut eocd, directory_size, 8);
|
||||
|
|
@ -200,7 +208,7 @@ pub struct ZipGenerator<'a> {
|
|||
pending_metadata: Vec<u8>,
|
||||
hasher: Hasher,
|
||||
hashes: Vec<u32>,
|
||||
output: Box<dyn LiveWriter + 'a>
|
||||
output: Box<dyn LiveWriter + 'a>,
|
||||
}
|
||||
|
||||
impl<'a> ZipGenerator<'a> {
|
||||
|
|
@ -225,8 +233,12 @@ impl<'a> ZipGenerator<'a> {
|
|||
fn finish_file(&mut self) {
|
||||
let hash = std::mem::replace(&mut self.hasher, Hasher::new()).finalize();
|
||||
self.hashes.push(hash);
|
||||
self.pending_metadata.append(&mut self.files[self.file_index].data_descriptor(hash));
|
||||
debug!("Finishing file entry in zipfile: {}, hash {}", self.files[self.file_index].name, hash);
|
||||
self.pending_metadata
|
||||
.append(&mut self.files[self.file_index].data_descriptor(hash));
|
||||
debug!(
|
||||
"Finishing file entry in zipfile: {}, hash {}",
|
||||
self.files[self.file_index].name, hash
|
||||
);
|
||||
self.file_index += 1;
|
||||
self.start_new_file();
|
||||
}
|
||||
|
|
@ -234,19 +246,27 @@ impl<'a> ZipGenerator<'a> {
|
|||
fn start_new_file(&mut self) {
|
||||
let mut offset = file_entries_size(&self.files[..self.file_index]);
|
||||
while self.file_index < self.files.len() && self.files[self.file_index].size == 0 {
|
||||
debug!("Empty file entry in zipfile: {}", self.files[self.file_index].name);
|
||||
debug!(
|
||||
"Empty file entry in zipfile: {}",
|
||||
self.files[self.file_index].name
|
||||
);
|
||||
self.hashes.push(EMPTY_STRING_CRC32);
|
||||
let mut local_header = self.files[self.file_index].local_header(offset);
|
||||
let mut data_descriptor = self.files[self.file_index].data_descriptor(EMPTY_STRING_CRC32);
|
||||
let mut data_descriptor =
|
||||
self.files[self.file_index].data_descriptor(EMPTY_STRING_CRC32);
|
||||
offset += local_header.len() + data_descriptor.len();
|
||||
self.file_index += 1;
|
||||
self.pending_metadata.append(&mut local_header);
|
||||
self.pending_metadata.append(&mut data_descriptor);
|
||||
}
|
||||
if self.file_index < self.files.len() {
|
||||
debug!("Starting file entry in zipfile: {}", self.files[self.file_index].name);
|
||||
debug!(
|
||||
"Starting file entry in zipfile: {}",
|
||||
self.files[self.file_index].name
|
||||
);
|
||||
self.byte_index = 0;
|
||||
self.pending_metadata.append(&mut self.files[self.file_index].local_header(offset));
|
||||
self.pending_metadata
|
||||
.append(&mut self.files[self.file_index].local_header(offset));
|
||||
} else {
|
||||
self.finish_zipfile();
|
||||
}
|
||||
|
|
@ -256,12 +276,17 @@ impl<'a> ZipGenerator<'a> {
|
|||
debug!("Writing zipfile central directory");
|
||||
let mut offset = 0;
|
||||
for (i, file) in self.files.iter().enumerate() {
|
||||
debug!("Writing central directory entry: {}, hash {}", file.name, self.hashes[i]);
|
||||
self.pending_metadata.append(&mut file.central_directory_header(offset, self.hashes[i]));
|
||||
debug!(
|
||||
"Writing central directory entry: {}, hash {}",
|
||||
file.name, self.hashes[i]
|
||||
);
|
||||
self.pending_metadata
|
||||
.append(&mut file.central_directory_header(offset, self.hashes[i]));
|
||||
offset += file_entry_size(file);
|
||||
}
|
||||
debug!("Writing end of central directory");
|
||||
self.pending_metadata.append(&mut end_of_central_directory(&self.files));
|
||||
self.pending_metadata
|
||||
.append(&mut end_of_central_directory(&self.files));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -276,8 +301,12 @@ impl<'a> Write for ZipGenerator<'a> {
|
|||
while !self.pending_metadata.is_empty() {
|
||||
let result = self.output.write(self.pending_metadata.as_slice());
|
||||
match result {
|
||||
Ok(0) | Err(_) => { return result; }
|
||||
Ok(n) => { self.pending_metadata.drain(..n); }
|
||||
Ok(0) | Err(_) => {
|
||||
return result;
|
||||
}
|
||||
Ok(n) => {
|
||||
self.pending_metadata.drain(..n);
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.file_index >= self.files.len() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue