use crate::{
common::{ArchiveError, Header, EOF_BLOCK},
FileParseError,
};
use std::{
fs::File,
io::{copy, Write},
path::{Path, PathBuf},
};
pub struct Writer {
file: std::fs::File,
paths: Vec<PathBuf>,
}
impl Writer {
pub fn new<P: AsRef<Path>>(path: P) -> Result<Writer, ArchiveError> {
Ok(Writer {
file: File::create(path).map_err(ArchiveError::FileCreation)?,
paths: vec![],
})
}
pub fn add<P: AsRef<Path>>(&mut self, path: P) -> Result<(), ArchiveError> {
let path = path.as_ref();
if path.is_dir() {
for entry in path.read_dir().map_err(ArchiveError::EntryAddition)? {
self.add(entry.map_err(ArchiveError::EntryAddition)?.path())?;
}
} else if path.is_file() {
self.paths.push(path.to_path_buf());
}
Ok(())
}
pub fn write(mut self) -> Result<(), ArchiveError> {
for path in self.paths.iter() {
let header = Header::from_file_metadata(path)?;
let mut handle = File::open(path).map_err(FileParseError::FileRead)?;
self.file
.write_all(&header.bytes)
.map_err(ArchiveError::FileWrite)?;
copy(&mut handle, &mut self.file).map_err(ArchiveError::FileWrite)?;
}
self.file
.write_all(EOF_BLOCK)
.map_err(ArchiveError::FileWrite)?;
Ok(())
}
pub fn files_count(&self) -> usize {
self.paths.len()
}
}