w3s/writer/
dir.rs

1//! Handles recursive walks in a directory and writes file bytes to the next writer
2//! 
3use super::*;
4use car_util::DirectoryItem;
5use std::cell::RefCell;
6use std::fs::File;
7use std::io;
8use std::rc::Rc;
9
10pub struct Dir<W: io::Write> {
11    curr_file_id: Rc<RefCell<u64>>,
12    next_writer: W,
13}
14
15impl<W: io::Write> Dir<W> {
16    pub fn new(curr_file_id: Rc<RefCell<u64>>, next_writer: W) -> Self {
17        Dir {
18            curr_file_id,
19            next_writer,
20        }
21    }
22
23    pub fn walk_write(&mut self, dir_items: &[DirectoryItem]) -> io::Result<()> {
24        for item in dir_items {
25            match item {
26                DirectoryItem::File(_, path, id) => {
27                    *self.curr_file_id.borrow_mut() = *id;
28                    let mut file = File::open(path)?;
29                    io::copy(&mut file, &mut self.next_writer)?;
30                    self.next_writer.flush()?;
31                }
32                DirectoryItem::Directory(_, sub_dir_items) => {
33                    self.walk_write(sub_dir_items)?;
34                }
35            }
36        }
37
38        Ok(())
39    }
40
41    #[cfg(feature = "zstd")]
42    pub fn walk_write_with_compression(
43        &mut self,
44        dir_items: &[DirectoryItem],
45        level: Option<i32>,
46    ) -> io::Result<()> {
47        for item in dir_items {
48            match item {
49                DirectoryItem::File(_, path, id) => {
50                    *self.curr_file_id.borrow_mut() = *id;
51                    let mut file = File::open(path)?;
52
53                    let mut compressor =
54                        zstd::stream::Encoder::new(&mut self.next_writer, level.unwrap_or(10))?;
55                    io::copy(&mut file, &mut compressor)?;
56
57                    compressor.finish()?;
58                    self.next_writer.flush()?;
59                }
60                DirectoryItem::Directory(_, sub_dir_items) => {
61                    self.walk_write_with_compression(sub_dir_items, level)?;
62                }
63            }
64        }
65
66        Ok(())
67    }
68
69    pub fn next(self) -> W {
70        self.next_writer
71    }
72}