use super::ArchiveWriterConfiguration;
use super::Filter;
use super::Format;
use super::Options;
use super::WriteEntry;
use crate::error::Error;
use crate::platform;
use crate::platform::ffi;
use std::os::fd::RawFd;
use std::path::Path;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct FileOptions {
pub options: Vec<Options>,
pub locales: Vec<String>,
}
impl Default for FileOptions {
fn default() -> Self {
Self {
options: Vec::new(),
locales: ArchiveWriterConfiguration::DEFAULT_LOCALES
.iter()
.map(|locale| locale.to_string())
.collect(),
}
}
}
pub struct ArchiveWriter {
pub(crate) handle: ffi::CzArchiveWriter,
}
unsafe impl Send for ArchiveWriter {}
impl ArchiveWriter {
pub fn new(configuration: &ArchiveWriterConfiguration) -> Result<Self, Error> {
let outcome = platform::outcome(
ffi::cz_archive_writer_new(configuration.clone()),
format!("make a {} archive writer", configuration.format.raw_value()),
)?;
Ok(Self {
handle: outcome.archive_writer(),
})
}
pub fn with_file(format: Format, filter: Filter, options: FileOptions, file: &Path) -> Result<Self, Error> {
let configuration = ArchiveWriterConfiguration {
format,
filter,
options: options.options,
locales: options.locales,
};
let outcome = platform::outcome(
ffi::cz_archive_writer_with_file(configuration, &file.display().to_string()),
format!("write a {} archive to {}", format.raw_value(), file.display()),
)?;
Ok(Self {
handle: outcome.archive_writer(),
})
}
pub fn open(&self, file: &Path) -> Result<(), Error> {
platform::outcome(
self.handle.open(&file.display().to_string()),
format!("open {} for an archive", file.display()),
)
.map(|_| ())
}
pub fn open_with_file_descriptor(&self, file_descriptor: RawFd) -> Result<(), Error> {
platform::outcome(
self.handle.open_with_file_descriptor(file_descriptor),
format!("open file descriptor {file_descriptor} for an archive"),
)
.map(|_| ())
}
pub fn finish_encoding(&self) -> Result<(), Error> {
platform::outcome(self.handle.finish_encoding(), "finish an archive").map(|_| ())
}
pub fn make_transaction_writer(&self) -> ArchiveWriterTransaction {
ArchiveWriterTransaction {
handle: self.handle.make_transaction_writer(),
}
}
pub fn write_entry(&self, entry: &WriteEntry, data: Option<&[u8]>) -> Result<(), Error> {
platform::outcome(
self.handle.write_entry(
entry.handle.duplicate(),
data.is_some(),
data.unwrap_or_default().to_vec(),
),
format!("write {} to an archive", entry.path().unwrap_or_default()),
)
.map(|_| ())
}
pub fn archive_directory(&self, dir: &Path) -> Result<(), Error> {
platform::outcome(
self.handle.archive_directory(&dir.display().to_string()),
format!("archive {}", dir.display()),
)
.map(|_| ())
}
pub fn archive(&self, paths: &[&Path], base: &Path) -> Result<(), Error> {
platform::outcome(
self.handle.archive(
paths
.iter()
.map(|path| path.display().to_string())
.collect(),
&base.display().to_string(),
),
format!("archive paths under {}", base.display()),
)
.map(|_| ())
}
}
pub struct ArchiveWriterTransaction {
handle: ffi::CzArchiveWriterTransaction,
}
unsafe impl Send for ArchiveWriterTransaction {}
impl ArchiveWriterTransaction {
pub fn write_header(&self, entry: &WriteEntry) -> Result<(), Error> {
platform::outcome(
self.handle.write_header(entry.handle.duplicate()),
format!("write the header of {} to an archive", entry.path().unwrap_or_default()),
)
.map(|_| ())
}
pub fn write_chunk(&self, data: &[u8]) -> Result<(), Error> {
platform::outcome(self.handle.write_chunk(data.to_vec()), "write a chunk to an archive").map(|_| ())
}
pub fn finish(&self) -> Result<(), Error> {
platform::outcome(self.handle.finish(), "finish an archive entry").map(|_| ())
}
}