tree_fs/
tree.rs

1use rand::{distr::Alphanumeric, rng, Rng};
2
3use std::env;
4use std::path::PathBuf;
5
6#[cfg(feature = "yaml")]
7use serde::Deserialize;
8#[cfg(feature = "yaml")]
9use serde::Serialize;
10
11/// Represents a file tree structure
12#[derive(Debug)]
13pub struct Tree {
14    /// Root folder where the tree will be created.
15    pub root: PathBuf,
16    /// Whether to automatically delete the temporary folder when dropped
17    pub drop: bool,
18}
19
20impl Drop for Tree {
21    fn drop(&mut self) {
22        if self.drop {
23            let _ = std::fs::remove_dir_all(&self.root);
24        }
25    }
26}
27
28/// Settings for entries in the tree.
29/// Currently supports read-only flag, but can be extended with additional settings.
30#[derive(Debug, Clone)]
31#[cfg_attr(feature = "yaml", derive(Deserialize, Serialize))]
32#[derive(Default)]
33pub struct Settings {
34    /// Whether the file is read-only.
35    #[cfg_attr(
36        feature = "yaml",
37        serde(default, skip_serializing_if = "std::ops::Not::not")
38    )]
39    pub readonly: bool,
40    // Future settings could be added here:
41    // pub timestamp: Option<SystemTime>,
42    // pub owner: Option<String>,
43    // etc.
44}
45
46// Builder pattern for Settings
47impl Settings {
48    /// Creates a new Settings with default values.
49    #[must_use]
50    pub fn new() -> Self {
51        Self::default()
52    }
53
54    /// Sets whether the file is read-only.
55    #[must_use]
56    pub const fn readonly(mut self, value: bool) -> Self {
57        self.readonly = value;
58        self
59    }
60}
61
62/// Describes what kind of entry to create
63#[derive(Debug, Clone)]
64#[cfg_attr(feature = "yaml", derive(Deserialize))]
65#[cfg_attr(feature = "yaml", serde(tag = "type"))]
66pub enum Kind {
67    /// A directory
68    #[cfg_attr(feature = "yaml", serde(rename = "directory"))]
69    Directory,
70    /// An empty file
71    #[cfg_attr(feature = "yaml", serde(rename = "empty_file"))]
72    EmptyFile,
73    /// A file with text content
74    #[cfg_attr(feature = "yaml", serde(rename = "text_file"))]
75    TextFile { content: String },
76}
77
78/// Represents an entry, file or directory, to be created.
79#[derive(Debug)]
80#[cfg_attr(feature = "yaml", derive(Deserialize))]
81pub struct Entry {
82    /// Path of the entry relative to the root folder.
83    pub path: PathBuf,
84    /// The kind of the entry
85    #[cfg_attr(feature = "yaml", serde(flatten))]
86    pub kind: Kind,
87    /// Optional settings for the entry
88    #[cfg_attr(
89        feature = "yaml",
90        serde(default, skip_serializing_if = "Option::is_none")
91    )]
92    pub settings: Option<Settings>,
93}
94
95/// Creates a temporary directory with a random name
96pub fn temp_dir() -> PathBuf {
97    let random_string: String = rng()
98        .sample_iter(&Alphanumeric)
99        .take(5)
100        .map(char::from)
101        .collect();
102
103    env::temp_dir().join(random_string)
104}