#![allow(clippy::unwrap_used, clippy::missing_panics_doc)]
use std::io::Cursor;
use std::io::Write;
#[must_use]
pub fn create_test_tar(entries: Vec<(&str, &[u8])>) -> Vec<u8> {
let mut ar = tar::Builder::new(Vec::new());
for (path, data) in entries {
let mut header = tar::Header::new_gnu();
header.set_size(data.len() as u64);
header.set_mode(0o644);
header.set_cksum();
ar.append_data(&mut header, path, data).unwrap();
}
ar.into_inner().unwrap()
}
#[must_use]
pub fn create_test_zip(entries: Vec<(&str, &[u8])>) -> Vec<u8> {
use zip::write::SimpleFileOptions;
use zip::write::ZipWriter;
let buffer = Vec::new();
let mut zip = ZipWriter::new(Cursor::new(buffer));
let options = SimpleFileOptions::default()
.compression_method(zip::CompressionMethod::Stored)
.unix_permissions(0o644);
for (path, data) in entries {
zip.start_file(path, options).unwrap();
zip.write_all(data).unwrap();
}
zip.finish().unwrap().into_inner()
}
pub struct TarTestBuilder {
builder: tar::Builder<Vec<u8>>,
}
impl TarTestBuilder {
#[must_use]
pub fn new() -> Self {
Self {
builder: tar::Builder::new(Vec::new()),
}
}
#[must_use]
pub fn add_file(mut self, path: &str, data: &[u8]) -> Self {
let mut header = tar::Header::new_gnu();
header.set_size(data.len() as u64);
header.set_mode(0o644);
header.set_cksum();
self.builder.append_data(&mut header, path, data).unwrap();
self
}
#[must_use]
pub fn add_file_with_mode(mut self, path: &str, data: &[u8], mode: u32) -> Self {
let mut header = tar::Header::new_gnu();
header.set_size(data.len() as u64);
header.set_mode(mode);
header.set_cksum();
self.builder.append_data(&mut header, path, data).unwrap();
self
}
#[must_use]
pub fn add_directory(mut self, path: &str) -> Self {
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_mode(0o755);
header.set_entry_type(tar::EntryType::Directory);
header.set_cksum();
self.builder
.append_data(&mut header, path, std::io::empty())
.unwrap();
self
}
#[must_use]
pub fn add_symlink(mut self, path: &str, target: &str) -> Self {
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_mode(0o777);
header.set_entry_type(tar::EntryType::Symlink);
header.set_link_name(target).unwrap();
header.set_cksum();
self.builder
.append_data(&mut header, path, std::io::empty())
.unwrap();
self
}
#[must_use]
pub fn add_hardlink(mut self, path: &str, target: &str) -> Self {
let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_mode(0o644);
header.set_entry_type(tar::EntryType::Link);
header.set_link_name(target).unwrap();
header.set_cksum();
self.builder
.append_data(&mut header, path, std::io::empty())
.unwrap();
self
}
#[must_use]
pub fn build(self) -> Vec<u8> {
self.builder.into_inner().unwrap()
}
}
impl Default for TarTestBuilder {
fn default() -> Self {
Self::new()
}
}
pub struct ZipTestBuilder {
zip: zip::ZipWriter<Cursor<Vec<u8>>>,
}
impl ZipTestBuilder {
#[must_use]
pub fn new() -> Self {
Self {
zip: zip::ZipWriter::new(Cursor::new(Vec::new())),
}
}
#[must_use]
pub fn add_file(mut self, path: &str, data: &[u8]) -> Self {
use zip::write::SimpleFileOptions;
let options = SimpleFileOptions::default()
.compression_method(zip::CompressionMethod::Stored)
.unix_permissions(0o644);
self.zip.start_file(path, options).unwrap();
self.zip.write_all(data).unwrap();
self
}
#[must_use]
pub fn add_file_with_mode(mut self, path: &str, data: &[u8], mode: u32) -> Self {
use zip::write::SimpleFileOptions;
let options = SimpleFileOptions::default()
.compression_method(zip::CompressionMethod::Stored)
.unix_permissions(mode);
self.zip.start_file(path, options).unwrap();
self.zip.write_all(data).unwrap();
self
}
#[must_use]
pub fn add_directory(mut self, path: &str) -> Self {
use zip::write::SimpleFileOptions;
let options = SimpleFileOptions::default().unix_permissions(0o755);
self.zip.add_directory(path, options).unwrap();
self
}
#[cfg(unix)]
#[must_use]
pub fn add_symlink(mut self, path: &str, target: &str) -> Self {
use zip::write::SimpleFileOptions;
let options = SimpleFileOptions::default().unix_permissions(0o120_777);
self.zip.start_file(path, options).unwrap();
self.zip.write_all(target.as_bytes()).unwrap();
self
}
#[must_use]
pub fn build(self) -> Vec<u8> {
self.zip.finish().unwrap().into_inner()
}
}
impl Default for ZipTestBuilder {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_create_test_tar() {
let tar_data = create_test_tar(vec![("file.txt", b"hello")]);
assert!(!tar_data.is_empty());
}
#[test]
fn test_create_test_zip() {
let zip_data = create_test_zip(vec![("file.txt", b"hello")]);
assert!(!zip_data.is_empty());
}
#[test]
fn test_tar_builder() {
let tar_data = TarTestBuilder::new()
.add_file("file.txt", b"content")
.add_directory("dir/")
.build();
assert!(!tar_data.is_empty());
}
#[test]
fn test_zip_builder() {
let zip_data = ZipTestBuilder::new()
.add_file("file.txt", b"content")
.add_directory("dir/")
.build();
assert!(!zip_data.is_empty());
}
}