1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
mod error;
mod impl_mergeable_tree;
mod impl_tree;

pub use error::*;

use crate::{Node, NodeContent};

/// Applying [`FileSystemTree`](crate::FileSystemTree) to the filesystem.
///
/// **Generic parameters:**
/// * `Name`: Identification of a child item.
/// * `Error`: Error type used by the other functions.
pub trait Build<Name, Error>: Node + Sized
where
    Self::DirectoryContent: IntoIterator<Item = (Name, Self)>,
{
    /// Locations of the items in the filesystem.
    type Path: Clone;
    /// Add prefix to the root of the tree.
    fn join(prefix: &Self::Path, name: &Name) -> Self::Path;
    /// Write content to a file.
    fn write_file(path: &Self::Path, content: &Self::FileContent) -> Result<(), Error>;
    /// Create a directory at root.
    fn create_dir(path: &Self::Path) -> Result<(), Error>;

    /// Build the tree into the filesystem.
    fn build(self, path: &Self::Path) -> Result<(), BuildError<Self::Path, Error>> {
        let children = match self.read() {
            NodeContent::File(content) => {
                return Self::write_file(&path, &content).map_err(|error| BuildError {
                    operation: FailedOperation::WriteFile,
                    path: path.clone(),
                    error,
                })
            }
            NodeContent::Directory(children) => children,
        };

        Self::create_dir(&path).map_err(|error| BuildError {
            operation: FailedOperation::CreateDir,
            path: path.clone(),
            error,
        })?;

        for (name, child) in children {
            child.build(&Self::join(&path, &name))?;
        }

        Ok(())
    }
}