1use crate::{
2 common::{ArchiveError, Header, EOF_BLOCK},
3 FileParseError,
4};
5use std::{
6 fs::File,
7 io::{copy, Write},
8 path::{Path, PathBuf},
9};
10
11pub struct Writer {
13 file: std::fs::File,
14 paths: Vec<PathBuf>,
15}
16impl Writer {
17 pub fn new<P: AsRef<Path>>(path: P) -> Result<Writer, ArchiveError> {
19 Ok(Writer {
20 file: File::create(path).map_err(ArchiveError::FileCreation)?,
21 paths: vec![],
22 })
23 }
24
25 pub fn add<P: AsRef<Path>>(&mut self, path: P) -> Result<(), ArchiveError> {
29 let path = path.as_ref();
30 if path.is_dir() {
34 for entry in path.read_dir().map_err(ArchiveError::EntryAddition)? {
35 self.add(entry.map_err(ArchiveError::EntryAddition)?.path())?;
36 }
37 } else if path.is_file() {
38 self.paths.push(path.to_path_buf());
39 }
40 Ok(())
42 }
43
44 pub fn write(mut self) -> Result<(), ArchiveError> {
48 for path in self.paths.iter() {
49 let header = Header::from_file_metadata(path)?;
50 let mut handle = File::open(path).map_err(FileParseError::FileRead)?;
51 self.file
52 .write_all(&header.bytes)
53 .map_err(ArchiveError::FileWrite)?;
54 copy(&mut handle, &mut self.file).map_err(ArchiveError::FileWrite)?;
55 }
56 self.file
58 .write_all(EOF_BLOCK)
59 .map_err(ArchiveError::FileWrite)?;
60 Ok(())
61 }
62
63 pub fn files_count(&self) -> usize {
64 self.paths.len()
65 }
66}