1 | use std::future::Future; |
2 | |
3 | use crate::io; |
4 | use crate::path::Path; |
5 | use crate::task::spawn_blocking; |
6 | |
7 | /// A builder for creating directories with configurable options. |
8 | /// |
9 | /// For Unix-specific options, import the [`os::unix::fs::DirBuilderExt`] trait. |
10 | /// |
11 | /// This type is an async version of [`std::fs::DirBuilder`]. |
12 | /// |
13 | /// [`os::unix::fs::DirBuilderExt`]: ../os/unix/fs/trait.DirBuilderExt.html |
14 | /// [`std::fs::DirBuilder`]: https://doc.rust-lang.org/std/fs/struct.DirBuilder.html |
15 | #[derive (Debug, Default)] |
16 | pub struct DirBuilder { |
17 | /// Set to `true` if non-existent parent directories should be created. |
18 | recursive: bool, |
19 | |
20 | /// Unix mode for newly created directories. |
21 | #[cfg (unix)] |
22 | mode: Option<u32>, |
23 | } |
24 | |
25 | impl DirBuilder { |
26 | /// Creates a blank set of options. |
27 | /// |
28 | /// The [`recursive`] option is initially set to `false`. |
29 | /// |
30 | /// [`recursive`]: #method.recursive |
31 | /// |
32 | /// # Examples |
33 | /// |
34 | /// ``` |
35 | /// use async_std::fs::DirBuilder; |
36 | /// |
37 | /// let builder = DirBuilder::new(); |
38 | /// ``` |
39 | pub fn new() -> DirBuilder { |
40 | #[cfg (not(unix))] |
41 | let builder = DirBuilder { recursive: false }; |
42 | |
43 | #[cfg (unix)] |
44 | let builder = DirBuilder { |
45 | recursive: false, |
46 | mode: None, |
47 | }; |
48 | |
49 | builder |
50 | } |
51 | |
52 | /// Sets the option for recursive mode. |
53 | /// |
54 | /// When set to `true`, this option means all parent directories should be created recursively |
55 | /// if they don't exist. Parents are created with the same permissions as the final directory. |
56 | /// |
57 | /// This option is initially set to `false`. |
58 | /// |
59 | /// # Examples |
60 | /// |
61 | /// ``` |
62 | /// use async_std::fs::DirBuilder; |
63 | /// |
64 | /// let mut builder = DirBuilder::new(); |
65 | /// builder.recursive(true); |
66 | /// ``` |
67 | pub fn recursive(&mut self, recursive: bool) -> &mut Self { |
68 | self.recursive = recursive; |
69 | self |
70 | } |
71 | |
72 | /// Creates a directory with the configured options. |
73 | /// |
74 | /// It is considered an error if the directory already exists unless recursive mode is enabled. |
75 | /// |
76 | /// # Errors |
77 | /// |
78 | /// An error will be returned in the following situations: |
79 | /// |
80 | /// * `path` already points to an existing file or directory. |
81 | /// * The current process lacks permissions to create the directory or its missing parents. |
82 | /// * Some other I/O error occurred. |
83 | /// |
84 | /// # Examples |
85 | /// |
86 | /// ```no_run |
87 | /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { |
88 | /// # |
89 | /// use async_std::fs::DirBuilder; |
90 | /// |
91 | /// DirBuilder::new() |
92 | /// .recursive(true) |
93 | /// .create("./some/directory" ) |
94 | /// .await?; |
95 | /// # |
96 | /// # Ok(()) }) } |
97 | /// ``` |
98 | pub fn create<P: AsRef<Path>>(&self, path: P) -> impl Future<Output = io::Result<()>> { |
99 | let mut builder = std::fs::DirBuilder::new(); |
100 | builder.recursive(self.recursive); |
101 | |
102 | #[cfg (unix)] |
103 | { |
104 | if let Some(mode) = self.mode { |
105 | std::os::unix::fs::DirBuilderExt::mode(&mut builder, mode); |
106 | } |
107 | } |
108 | |
109 | let path = path.as_ref().to_owned(); |
110 | async move { spawn_blocking(move || builder.create(path)).await } |
111 | } |
112 | } |
113 | |
114 | cfg_unix! { |
115 | use crate::os::unix::fs::DirBuilderExt; |
116 | |
117 | impl DirBuilderExt for DirBuilder { |
118 | fn mode(&mut self, mode: u32) -> &mut Self { |
119 | self.mode = Some(mode); |
120 | self |
121 | } |
122 | } |
123 | } |
124 | |