fut_compat/fs/mod.rs
1use std::path::{Path, PathBuf};
2use std::fs::{Metadata, Permissions, FileType};
3use std::ffi::OsString;
4
5use futures::stream::Stream;
6
7use async_trait::async_trait;
8
9
10
11/// Contains the compatibility objects for the [`tokio`](https://docs.rs/tokio) runtime.
12#[cfg(feature = "tokio-rt")]
13#[cfg_attr(docsrs, doc(cfg(feature = "tokio-rt")))]
14mod tokio;
15#[cfg(feature = "tokio-rt")]
16#[cfg_attr(docsrs, doc(cfg(feature = "tokio-rt")))]
17pub use self::tokio::*;
18
19/// Contains the compatibility objects for the [`async_std`](https://docs.rs/async-std) runtime.
20#[cfg(feature = "async-std-rt")]
21#[cfg_attr(docsrs, doc(cfg(feature = "async-std-rt")))]
22mod async_std;
23#[cfg(feature = "async-std-rt")]
24#[cfg_attr(docsrs, doc(cfg(feature = "async-std-rt")))]
25pub use self::async_std::*;
26
27
28
29/// An async abstraction over the functions in [`std::fs`].
30#[async_trait]
31pub trait Filesystem {
32 type ReadDir: Stream<Item = std::io::Result<Self::DirEntry>>;
33 type DirEntry: DirEntry;
34
35 /// Returns the canonical form of a path.
36 ///
37 /// The returned path is in absolute form with all intermediate components normalized and symbolic
38 /// links resolved.
39 ///
40 /// This function is an async version of [`std::fs::canonicalize`].
41 ///
42 /// [`std::fs::canonicalize`]: https://doc.rust-lang.org/std/fs/fn.canonicalize.html
43 ///
44 /// # Errors
45 ///
46 /// An error will be returned in the following situations:
47 ///
48 /// * `path` does not point to an existing file or directory.
49 /// * A non-final component in `path` is not a directory.
50 /// * Some other I/O error occurred.
51 ///
52 /// # Examples
53 ///
54 /// Using the [`tokio`](https://docs.rs/tokio) runtime:
55 ///
56 /// ```no_run
57 /// # #[tokio::main]
58 /// # async fn main() -> std::io::Result<()> {
59 /// #
60 /// use fut_compat::fs::Filesystem;
61 /// use fut_compat::fs::TokioFs;
62 ///
63 /// let path = TokioFs::canonicalize(".").await?;
64 /// #
65 /// # Ok(())
66 /// # }
67 /// ```
68 ///
69 /// Using the [`async_std`](https://docs.rs/async-std) runtime:
70 ///
71 /// ```no_run
72 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
73 /// #
74 /// use fut_compat::fs::Filesystem;
75 /// use fut_compat::fs::AsyncStdFs;
76 ///
77 /// let path = AsyncStdFs::canonicalize(".").await?;
78 /// #
79 /// # Ok(()) }) }
80 /// ```
81 async fn canonicalize<P: AsRef<Path> + Send>(path: P) -> std::io::Result<PathBuf>;
82
83 /// Copies the contents and permissions of a file to a new location.
84 ///
85 /// On success, the total number of bytes copied is returned and equals the length of the `to` file
86 /// after this operation.
87 ///
88 /// The old contents of `to` will be overwritten. If `from` and `to` both point to the same file,
89 /// then the file will likely get truncated as a result of this operation.
90 ///
91 /// If you're working with open [`File`]s and want to copy contents through those types, use the
92 /// [`io::copy`] function.
93 ///
94 /// This function is an async version of [`std::fs::copy`].
95 ///
96 /// [`File`]: struct.File.html
97 /// [`io::copy`]: ../io/fn.copy.html
98 /// [`std::fs::copy`]: https://doc.rust-lang.org/std/fs/fn.copy.html
99 ///
100 /// # Errors
101 ///
102 /// An error will be returned in the following situations:
103 ///
104 /// * `from` does not point to an existing file.
105 /// * The current process lacks permissions to read `from` or write `to`.
106 /// * Some other I/O error occurred.
107 ///
108 /// # Examples
109 ///
110 /// Using the [`tokio`](https://docs.rs/tokio) runtime:
111 ///
112 /// ```no_run
113 /// # #[tokio::main]
114 /// # async fn main() -> std::io::Result<()> {
115 /// #
116 /// use fut_compat::fs::Filesystem;
117 /// use fut_compat::fs::TokioFs;
118 ///
119 /// let num_bytes = TokioFs::copy("a.txt", "b.txt").await?;
120 /// #
121 /// # Ok(())
122 /// # }
123 /// ```
124 ///
125 /// Using the [`async_std`](https://docs.rs/async-std) runtime:
126 ///
127 /// ```no_run
128 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
129 /// #
130 /// use fut_compat::fs::Filesystem;
131 /// use fut_compat::fs::AsyncStdFs;
132 ///
133 /// let num_bytes = AsyncStdFs::copy("a.txt", "b.txt").await?;
134 /// #
135 /// # Ok(()) }) }
136 /// ```
137 async fn copy<S: AsRef<Path> + Send, D: AsRef<Path> + Send>(
138 from: S,
139 to: D,
140 ) -> std::io::Result<u64>;
141
142 /// Creates a new directory.
143 ///
144 /// Note that this function will only create the final directory in `path`. If you want to create
145 /// all of its missing parent directories too, use the [`create_dir_all`] function instead.
146 ///
147 /// This function is an async version of [`std::fs::create_dir`].
148 ///
149 /// [`create_dir_all`]: fn.create_dir_all.html
150 /// [`std::fs::create_dir`]: https://doc.rust-lang.org/std/fs/fn.create_dir.html
151 ///
152 /// # Errors
153 ///
154 /// An error will be returned in the following situations:
155 ///
156 /// * `path` already points to an existing file or directory.
157 /// * A parent directory in `path` does not exist.
158 /// * The current process lacks permissions to create the directory.
159 /// * Some other I/O error occurred.
160 ///
161 /// # Examples
162 ///
163 /// Using the [`tokio`](https://docs.rs/tokio) runtime:
164 ///
165 /// ```no_run
166 /// # #[tokio::main]
167 /// # async fn main() -> std::io::Result<()> {
168 /// #
169 /// use fut_compat::fs::Filesystem;
170 /// use fut_compat::fs::TokioFs;
171 ///
172 /// TokioFs::create_dir("./some/directory").await?;
173 /// #
174 /// # Ok(())
175 /// # }
176 /// ```
177 ///
178 /// Using the [`async_std`](https://docs.rs/async-std) runtime:
179 ///
180 /// ```no_run
181 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
182 /// #
183 /// use fut_compat::fs::Filesystem;
184 /// use fut_compat::fs::AsyncStdFs;
185 ///
186 /// AsyncStdFs::create_dir("./some/directory").await?;
187 /// #
188 /// # Ok(()) }) }
189 /// ```
190 async fn create_dir<P: AsRef<Path> + Send>(path: P) -> std::io::Result<()>;
191
192 /// Creates a new directory and all of its parents if they are missing.
193 ///
194 /// This function is an async version of [`std::fs::create_dir_all`].
195 ///
196 /// [`std::fs::create_dir_all`]: https://doc.rust-lang.org/std/fs/fn.create_dir_all.html
197 ///
198 /// # Errors
199 ///
200 /// An error will be returned in the following situations:
201 ///
202 /// * `path` already points to an existing file or directory.
203 /// * The current process lacks permissions to create the directory or its missing parents.
204 /// * Some other I/O error occurred.
205 ///
206 /// # Examples
207 ///
208 /// Using the [`tokio`](https://docs.rs/tokio) runtime:
209 ///
210 /// ```no_run
211 /// # #[tokio::main]
212 /// # async fn main() -> std::io::Result<()> {
213 /// #
214 /// use fut_compat::fs::Filesystem;
215 /// use fut_compat::fs::TokioFs;
216 ///
217 /// TokioFs::create_dir_all("./some/directory").await?;
218 /// #
219 /// # Ok(())
220 /// # }
221 /// ```
222 ///
223 /// Using the [`async_std`](https://docs.rs/async-std) runtime:
224 ///
225 /// ```no_run
226 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
227 /// #
228 /// use fut_compat::fs::Filesystem;
229 /// use fut_compat::fs::AsyncStdFs;
230 ///
231 /// AsyncStdFs::create_dir_all("./some/directory").await?;
232 /// #
233 /// # Ok(()) }) }
234 /// ```
235 async fn create_dir_all<P: AsRef<Path> + Send>(path: P) -> std::io::Result<()>;
236
237 /// Creates a hard link on the filesystem.
238 ///
239 /// The `dst` path will be a link pointing to the `src` path. Note that operating systems often
240 /// require these two paths to be located on the same filesystem.
241 ///
242 /// This function is an async version of [`std::fs::hard_link`].
243 ///
244 /// [`std::fs::hard_link`]: https://doc.rust-lang.org/std/fs/fn.hard_link.html
245 ///
246 /// # Errors
247 ///
248 /// An error will be returned in the following situations:
249 ///
250 /// * `src` does not point to an existing file.
251 /// * Some other I/O error occurred.
252 ///
253 /// # Examples
254 ///
255 /// Using the [`tokio`](https://docs.rs/tokio) runtime:
256 ///
257 /// ```no_run
258 /// # #[tokio::main]
259 /// # async fn main() -> std::io::Result<()> {
260 /// #
261 /// use fut_compat::fs::Filesystem;
262 /// use fut_compat::fs::TokioFs;
263 ///
264 /// TokioFs::hard_link("a.txt", "b.txt").await?;
265 /// #
266 /// # Ok(())
267 /// # }
268 /// ```
269 ///
270 /// Using the [`async_std`](https://docs.rs/async-std) runtime:
271 ///
272 /// ```no_run
273 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
274 /// #
275 /// use fut_compat::fs::Filesystem;
276 /// use fut_compat::fs::AsyncStdFs;
277 ///
278 /// AsyncStdFs::hard_link("a.txt", "b.txt").await?;
279 /// #
280 /// # Ok(()) }) }
281 /// ```
282 async fn hard_link<S: AsRef<Path> + Send, D: AsRef<Path> + Send>(
283 from: S,
284 to: D,
285 ) -> std::io::Result<()>;
286
287 /// Reads metadata for a path.
288 ///
289 /// This function will traverse symbolic links to read metadata for the target file or directory.
290 /// If you want to read metadata without following symbolic links, use [`symlink_metadata`]
291 /// instead.
292 ///
293 /// This function is an async version of [`std::fs::metadata`].
294 ///
295 /// [`symlink_metadata`]: fn.symlink_metadata.html
296 /// [`std::fs::metadata`]: https://doc.rust-lang.org/std/fs/fn.metadata.html
297 ///
298 /// # Errors
299 ///
300 /// An error will be returned in the following situations:
301 ///
302 /// * `path` does not point to an existing file or directory.
303 /// * The current process lacks permissions to read metadata for the path.
304 /// * Some other I/O error occurred.
305 ///
306 /// # Examples
307 ///
308 /// Using the [`tokio`](https://docs.rs/tokio) runtime:
309 ///
310 /// ```no_run
311 /// # #[tokio::main]
312 /// # async fn main() -> std::io::Result<()> {
313 /// #
314 /// use fut_compat::fs::Filesystem;
315 /// use fut_compat::fs::TokioFs;
316 ///
317 /// let meta = TokioFs::metadata("a.txt").await?;
318 /// #
319 /// # Ok(())
320 /// # }
321 /// ```
322 ///
323 /// Using the [`async_std`](https://docs.rs/async-std) runtime:
324 ///
325 /// ```no_run
326 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
327 /// #
328 /// use fut_compat::fs::Filesystem;
329 /// use fut_compat::fs::AsyncStdFs;
330 ///
331 /// let meta = AsyncStdFs::metadata("a.txt").await?;
332 /// #
333 /// # Ok(()) }) }
334 /// ```
335 async fn metadata<P: AsRef<Path> + Send>(path: P) -> std::io::Result<Metadata>;
336
337 /// Reads the entire contents of a file as raw bytes.
338 ///
339 /// This is a convenience function for reading entire files. It pre-allocates a buffer based on the
340 /// file size when available, so it is typically faster than manually opening a file and reading
341 /// from it.
342 ///
343 /// If you want to read the contents as a string, use [`read_to_string`] instead.
344 ///
345 /// This function is an async version of [`std::fs::read`].
346 ///
347 /// [`read_to_string`]: fn.read_to_string.html
348 /// [`std::fs::read`]: https://doc.rust-lang.org/std/fs/fn.read.html
349 ///
350 /// # Errors
351 ///
352 /// An error will be returned in the following situations:
353 ///
354 /// * `path` does not point to an existing file.
355 /// * The current process lacks permissions to read the file.
356 /// * Some other I/O error occurred.
357 ///
358 /// # Examples
359 ///
360 /// Using the [`tokio`](https://docs.rs/tokio) runtime:
361 ///
362 /// ```no_run
363 /// # #[tokio::main]
364 /// # async fn main() -> std::io::Result<()> {
365 /// #
366 /// use fut_compat::fs::Filesystem;
367 /// use fut_compat::fs::TokioFs;
368 ///
369 /// let contents = TokioFs::read("a.txt").await?;
370 /// #
371 /// # Ok(())
372 /// # }
373 /// ```
374 ///
375 /// Using the [`async_std`](https://docs.rs/async-std) runtime:
376 ///
377 /// ```no_run
378 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
379 /// #
380 /// use fut_compat::fs::Filesystem;
381 /// use fut_compat::fs::AsyncStdFs;
382 ///
383 /// let contents = AsyncStdFs::read("a.txt").await?;
384 /// #
385 /// # Ok(()) }) }
386 /// ```
387 async fn read<P: AsRef<Path> + Send>(path: P) -> std::io::Result<Vec<u8>>;
388
389 /// Returns a stream of entries in a directory.
390 ///
391 /// The stream yields items of type [`io::Result`]`<`[`DirEntry`]`>`. Note that I/O errors can
392 /// occur while reading from the stream.
393 ///
394 /// This function is an async version of [`std::fs::read_dir`].
395 ///
396 /// [`io::Result`]: ../io/type.Result.html
397 /// [`DirEntry`]: struct.DirEntry.html
398 /// [`std::fs::read_dir`]: https://doc.rust-lang.org/std/fs/fn.read_dir.html
399 ///
400 /// # Errors
401 ///
402 /// An error will be returned in the following situations:
403 ///
404 /// * `path` does not point to an existing directory.
405 /// * The current process lacks permissions to read the contents of the directory.
406 /// * Some other I/O error occurred.
407 ///
408 /// # Examples
409 ///
410 /// Using the [`tokio`](https://docs.rs/tokio) runtime:
411 ///
412 /// ```no_run
413 /// # #[tokio::main]
414 /// # async fn main() -> std::io::Result<()> {
415 /// #
416 /// use futures::stream::StreamExt;
417 /// use fut_compat::fs::Filesystem;
418 /// use fut_compat::fs::TokioFs;
419 ///
420 /// let mut entries = TokioFs::read_dir(".").await?;
421 ///
422 /// while let Some(res) = entries.next().await {
423 /// let entry = res?;
424 /// println!("{}", entry.file_name().to_string_lossy());
425 /// }
426 /// #
427 /// # Ok(())
428 /// # }
429 /// ```
430 ///
431 /// Using the [`async_std`](https://docs.rs/async-std) runtime:
432 ///
433 /// ```no_run
434 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
435 /// #
436 /// use futures::stream::StreamExt;
437 /// use fut_compat::fs::Filesystem;
438 /// use fut_compat::fs::AsyncStdFs;
439 ///
440 /// let mut entries = AsyncStdFs::read_dir(".").await?;
441 ///
442 /// while let Some(res) = entries.next().await {
443 /// let entry = res?;
444 /// println!("{}", entry.file_name().to_string_lossy());
445 /// }
446 /// #
447 /// # Ok(()) }) }
448 /// ```
449 async fn read_dir<P: AsRef<Path> + Send>(path: P) -> std::io::Result<Self::ReadDir>;
450
451 /// Reads a symbolic link and returns the path it points to.
452 ///
453 /// This function is an async version of [`std::fs::read_link`].
454 ///
455 /// [`std::fs::read_link`]: https://doc.rust-lang.org/std/fs/fn.read_link.html
456 ///
457 /// # Errors
458 ///
459 /// An error will be returned in the following situations:
460 ///
461 /// * `path` does not point to an existing link.
462 /// * Some other I/O error occurred.
463 ///
464 /// # Examples
465 ///
466 /// Using the [`tokio`](https://docs.rs/tokio) runtime:
467 ///
468 /// ```no_run
469 /// # #[tokio::main]
470 /// # async fn main() -> std::io::Result<()> {
471 /// #
472 /// use fut_compat::fs::Filesystem;
473 /// use fut_compat::fs::TokioFs;
474 ///
475 /// let path = TokioFs::read_link("a.txt").await?;
476 /// #
477 /// # Ok(())
478 /// # }
479 /// ```
480 ///
481 /// Using the [`async_std`](https://docs.rs/async-std) runtime:
482 ///
483 /// ```no_run
484 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
485 /// #
486 /// use fut_compat::fs::Filesystem;
487 /// use fut_compat::fs::AsyncStdFs;
488 ///
489 /// let path = AsyncStdFs::read_link("a.txt").await?;
490 /// #
491 /// # Ok(()) }) }
492 /// ```
493 async fn read_link<P: AsRef<Path> + Send>(path: P) -> std::io::Result<PathBuf>;
494
495 /// Reads the entire contents of a file as a string.
496 ///
497 /// This is a convenience function for reading entire files. It pre-allocates a string based on the
498 /// file size when available, so it is typically faster than manually opening a file and reading
499 /// from it.
500 ///
501 /// If you want to read the contents as raw bytes, use [`read`] instead.
502 ///
503 /// This function is an async version of [`std::fs::read_to_string`].
504 ///
505 /// [`read`]: #tymethod.read
506 /// [`std::fs::read_to_string`]: https://doc.rust-lang.org/std/fs/fn.read_to_string.html
507 ///
508 /// # Errors
509 ///
510 /// An error will be returned in the following situations:
511 ///
512 /// * `path` does not point to an existing file.
513 /// * The current process lacks permissions to read the file.
514 /// * The contents of the file cannot be read as a UTF-8 string.
515 /// * Some other I/O error occurred.
516 ///
517 /// # Examples
518 ///
519 /// Using the [`tokio`](https://docs.rs/tokio) runtime:
520 ///
521 /// ```no_run
522 /// # #[tokio::main]
523 /// # async fn main() -> std::io::Result<()> {
524 /// #
525 /// use fut_compat::fs::Filesystem;
526 /// use fut_compat::fs::TokioFs;
527 ///
528 /// let contents = TokioFs::read_to_string("a.txt").await?;
529 /// #
530 /// # Ok(())
531 /// # }
532 /// ```
533 ///
534 /// Using the [`async_std`](https://docs.rs/async-std) runtime:
535 ///
536 /// ```no_run
537 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
538 /// #
539 /// use fut_compat::fs::Filesystem;
540 /// use fut_compat::fs::AsyncStdFs;
541 ///
542 /// let contents = AsyncStdFs::read_to_string("a.txt").await?;
543 /// #
544 /// # Ok(()) }) }
545 /// ```
546 async fn read_to_string<P: AsRef<Path> + Send>(path: P) -> std::io::Result<String>;
547
548 /// Removes an empty directory.
549 ///
550 /// This function is an async version of [`std::fs::remove_dir`].
551 ///
552 /// [`std::fs::remove_dir`]: https://doc.rust-lang.org/std/fs/fn.remove_dir.html
553 ///
554 /// # Errors
555 ///
556 /// An error will be returned in the following situations:
557 ///
558 /// * `path` is not an existing and empty directory.
559 /// * The current process lacks permissions to remove the directory.
560 /// * Some other I/O error occurred.
561 ///
562 /// # Examples
563 ///
564 /// Using the [`tokio`](https://docs.rs/tokio) runtime:
565 ///
566 /// ```no_run
567 /// # #[tokio::main]
568 /// # async fn main() -> std::io::Result<()> {
569 /// #
570 /// use fut_compat::fs::Filesystem;
571 /// use fut_compat::fs::TokioFs;
572 ///
573 /// TokioFs::remove_dir("./some/directory").await?;
574 /// #
575 /// # Ok(())
576 /// # }
577 /// ```
578 ///
579 /// Using the [`async_std`](https://docs.rs/async-std) runtime:
580 ///
581 /// ```no_run
582 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
583 /// #
584 /// use fut_compat::fs::Filesystem;
585 /// use fut_compat::fs::AsyncStdFs;
586 ///
587 /// AsyncStdFs::remove_dir("./some/directory").await?;
588 /// #
589 /// # Ok(()) }) }
590 /// ```
591 async fn remove_dir<P: AsRef<Path> + Send>(path: P) -> std::io::Result<()>;
592
593 /// Removes a directory and all of its contents.
594 ///
595 /// This function is an async version of [`std::fs::remove_dir_all`].
596 ///
597 /// [`std::fs::remove_dir_all`]: https://doc.rust-lang.org/std/fs/fn.remove_dir_all.html
598 ///
599 /// # Errors
600 ///
601 /// An error will be returned in the following situations:
602 ///
603 /// * `path` is not an existing and empty directory.
604 /// * The current process lacks permissions to remove the directory.
605 /// * Some other I/O error occurred.
606 ///
607 /// # Examples
608 ///
609 /// Using the [`tokio`](https://docs.rs/tokio) runtime:
610 ///
611 /// ```no_run
612 /// # #[tokio::main]
613 /// # async fn main() -> std::io::Result<()> {
614 /// #
615 /// use fut_compat::fs::Filesystem;
616 /// use fut_compat::fs::TokioFs;
617 ///
618 /// TokioFs::remove_dir_all("./some/directory").await?;
619 /// #
620 /// # Ok(())
621 /// # }
622 /// ```
623 ///
624 /// Using the [`async_std`](https://docs.rs/async-std) runtime:
625 ///
626 /// ```no_run
627 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
628 /// #
629 /// use fut_compat::fs::Filesystem;
630 /// use fut_compat::fs::AsyncStdFs;
631 ///
632 /// AsyncStdFs::remove_dir_all("./some/directory").await?;
633 /// #
634 /// # Ok(()) }) }
635 /// ```
636 async fn remove_dir_all<P: AsRef<Path> + Send>(path: P) -> std::io::Result<()>;
637
638 /// Removes a file.
639 ///
640 /// This function is an async version of [`std::fs::remove_file`].
641 ///
642 /// [`std::fs::remove_file`]: https://doc.rust-lang.org/std/fs/fn.remove_file.html
643 ///
644 /// # Errors
645 ///
646 /// An error will be returned in the following situations:
647 ///
648 /// * `path` does not point to an existing file.
649 /// * The current process lacks permissions to remove the file.
650 /// * Some other I/O error occurred.
651 ///
652 /// # Examples
653 ///
654 /// Using the [`tokio`](https://docs.rs/tokio) runtime:
655 ///
656 /// ```no_run
657 /// # #[tokio::main]
658 /// # async fn main() -> std::io::Result<()> {
659 /// #
660 /// use fut_compat::fs::Filesystem;
661 /// use fut_compat::fs::TokioFs;
662 ///
663 /// TokioFs::remove_file("a.txt").await?;
664 /// #
665 /// # Ok(())
666 /// # }
667 /// ```
668 ///
669 /// Using the [`async_std`](https://docs.rs/async-std) runtime:
670 ///
671 /// ```no_run
672 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
673 /// #
674 /// use fut_compat::fs::Filesystem;
675 /// use fut_compat::fs::AsyncStdFs;
676 ///
677 /// AsyncStdFs::remove_file("a.txt").await?;
678 /// #
679 /// # Ok(()) }) }
680 /// ```
681 async fn remove_file<P: AsRef<Path> + Send>(path: P) -> std::io::Result<()>;
682
683 /// Renames a file or directory to a new location.
684 ///
685 /// If a file or directory already exists at the target location, it will be overwritten by this
686 /// operation.
687 ///
688 /// This function is an async version of [`std::fs::rename`].
689 ///
690 /// [`std::fs::rename`]: https://doc.rust-lang.org/std/fs/fn.rename.html
691 ///
692 /// # Errors
693 ///
694 /// An error will be returned in the following situations:
695 ///
696 /// * `from` does not point to an existing file or directory.
697 /// * `from` and `to` are on different filesystems.
698 /// * The current process lacks permissions to do the rename operation.
699 /// * Some other I/O error occurred.
700 ///
701 /// # Examples
702 ///
703 /// Using the [`tokio`](https://docs.rs/tokio) runtime:
704 ///
705 /// ```no_run
706 /// # #[tokio::main]
707 /// # async fn main() -> std::io::Result<()> {
708 /// #
709 /// use fut_compat::fs::Filesystem;
710 /// use fut_compat::fs::TokioFs;
711 ///
712 /// TokioFs::rename("a.txt", "b.txt").await?;
713 /// #
714 /// # Ok(())
715 /// # }
716 /// ```
717 ///
718 /// Using the [`async_std`](https://docs.rs/async-std) runtime:
719 ///
720 /// ```no_run
721 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
722 /// #
723 /// use fut_compat::fs::Filesystem;
724 /// use fut_compat::fs::AsyncStdFs;
725 ///
726 /// AsyncStdFs::rename("a.txt", "b.txt").await?;
727 /// #
728 /// # Ok(()) }) }
729 /// ```
730 async fn rename<O: AsRef<Path> + Send, N: AsRef<Path> + Send>(
731 from: O,
732 to: N,
733 ) -> std::io::Result<()>;
734
735 /// Changes the permissions of a file or directory.
736 ///
737 /// This function is an async version of [`std::fs::set_permissions`].
738 ///
739 /// [`std::fs::set_permissions`]: https://doc.rust-lang.org/std/fs/fn.set_permissions.html
740 ///
741 /// # Errors
742 ///
743 /// An error will be returned in the following situations:
744 ///
745 /// * `path` does not point to an existing file or directory.
746 /// * The current process lacks permissions to change attributes on the file or directory.
747 /// * Some other I/O error occurred.
748 ///
749 /// # Examples
750 ///
751 /// Using the [`tokio`](https://docs.rs/tokio) runtime:
752 ///
753 /// ```no_run
754 /// # #[tokio::main]
755 /// # async fn main() -> std::io::Result<()> {
756 /// #
757 /// use fut_compat::fs::Filesystem;
758 /// use fut_compat::fs::TokioFs;
759 ///
760 /// let mut perm = TokioFs::metadata("a.txt").await?.permissions();
761 /// perm.set_readonly(true);
762 /// TokioFs::set_permissions("a.txt", perm).await?;
763 /// #
764 /// # Ok(())
765 /// # }
766 /// ```
767 ///
768 /// Using the [`async_std`](https://docs.rs/async-std) runtime:
769 ///
770 /// ```no_run
771 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
772 /// #
773 /// use fut_compat::fs::Filesystem;
774 /// use fut_compat::fs::AsyncStdFs;
775 ///
776 /// let mut perm = AsyncStdFs::metadata("a.txt").await?.permissions();
777 /// perm.set_readonly(true);
778 /// AsyncStdFs::set_permissions("a.txt", perm).await?;
779 /// #
780 /// # Ok(()) }) }
781 /// ```
782 async fn set_permissions<P: AsRef<Path> + Send>(
783 path: P,
784 perm: Permissions,
785 ) -> std::io::Result<()>;
786
787 /// Reads metadata for a path without following symbolic links.
788 ///
789 /// If you want to follow symbolic links before reading metadata of the target file or directory,
790 /// use [`metadata`] instead.
791 ///
792 /// This function is an async version of [`std::fs::symlink_metadata`].
793 ///
794 /// [`metadata`]: fn.metadata.html
795 /// [`std::fs::symlink_metadata`]: https://doc.rust-lang.org/std/fs/fn.symlink_metadata.html
796 ///
797 /// # Errors
798 ///
799 /// An error will be returned in the following situations:
800 ///
801 /// * `path` does not point to an existing file or directory.
802 /// * The current process lacks permissions to read metadata for the path.
803 /// * Some other I/O error occurred.
804 ///
805 /// # Examples
806 ///
807 /// Using the [`tokio`](https://docs.rs/tokio) runtime:
808 ///
809 /// ```no_run
810 /// # #[tokio::main]
811 /// # async fn main() -> std::io::Result<()> {
812 /// #
813 /// use fut_compat::fs::Filesystem;
814 /// use fut_compat::fs::TokioFs;
815 ///
816 /// let meta = TokioFs::symlink_metadata("a.txt").await?;
817 /// #
818 /// # Ok(())
819 /// # }
820 /// ```
821 ///
822 /// Using the [`async_std`](https://docs.rs/async-std) runtime:
823 ///
824 /// ```no_run
825 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
826 /// #
827 /// use fut_compat::fs::Filesystem;
828 /// use fut_compat::fs::AsyncStdFs;
829 ///
830 /// let meta = AsyncStdFs::symlink_metadata("a.txt").await?;
831 /// #
832 /// # Ok(()) }) }
833 /// ```
834 async fn symlink_metadata<P: AsRef<Path> + Send>(path: P) -> std::io::Result<Metadata>;
835
836 /// Writes a slice of bytes as the new contents of a file.
837 ///
838 /// This function will create a file if it does not exist, and will entirely replace its contents
839 /// if it does.
840 ///
841 /// This function is an async version of [`std::fs::write`].
842 ///
843 /// [`std::fs::write`]: https://doc.rust-lang.org/std/fs/fn.write.html
844 ///
845 /// # Errors
846 ///
847 /// An error will be returned in the following situations:
848 ///
849 /// * The file's parent directory does not exist.
850 /// * The current process lacks permissions to write to the file.
851 /// * Some other I/O error occurred.
852 ///
853 /// # Examples
854 ///
855 /// Using the [`tokio`](https://docs.rs/tokio) runtime:
856 ///
857 /// ```no_run
858 /// # #[tokio::main]
859 /// # async fn main() -> std::io::Result<()> {
860 /// #
861 /// use fut_compat::fs::Filesystem;
862 /// use fut_compat::fs::TokioFs;
863 ///
864 /// TokioFs::write("a.txt", b"Hello world!").await?;
865 /// #
866 /// # Ok(())
867 /// # }
868 /// ```
869 ///
870 /// Using the [`async_std`](https://docs.rs/async-std) runtime:
871 ///
872 /// ```no_run
873 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
874 /// #
875 /// use fut_compat::fs::Filesystem;
876 /// use fut_compat::fs::AsyncStdFs;
877 ///
878 /// AsyncStdFs::write("a.txt", b"Hello world!").await?;
879 /// #
880 /// # Ok(()) }) }
881 /// ```
882 async fn write<P: AsRef<Path> + Send, C: AsRef<[u8]> + Send>(
883 path: P,
884 contents: C
885 ) -> std::io::Result<()>;
886}
887
888
889
890/// An async abstraction over [`std::fs::DirEntry`].
891#[async_trait]
892pub trait DirEntry {
893 /// Returns the full path to this entry.
894 ///
895 /// The full path is created by joining the original path passed to [`read_dir`] with the name
896 /// of this entry.
897 ///
898 /// [`read_dir`]: trait.Filesystem.html#tymethod.read_dir
899 ///
900 /// # Examples
901 ///
902 /// Using the [`tokio`](https://docs.rs/tokio) runtime:
903 ///
904 /// ```no_run
905 /// # #[tokio::main]
906 /// # async fn main() -> std::io::Result<()> {
907 /// #
908 /// use futures::stream::StreamExt;
909 /// use fut_compat::fs::Filesystem;
910 /// use fut_compat::fs::TokioFs;
911 ///
912 /// let mut entries = TokioFs::read_dir(".").await?;
913 ///
914 /// while let Some(res) = entries.next().await {
915 /// let entry = res?;
916 /// println!("{:?}", entry.path());
917 /// }
918 /// #
919 /// # Ok(())
920 /// # }
921 /// ```
922 ///
923 /// Using the [`async_std`](https://docs.rs/async-std) runtime:
924 ///
925 /// ```no_run
926 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
927 /// #
928 /// use futures::stream::StreamExt;
929 /// use fut_compat::fs::Filesystem;
930 /// use fut_compat::fs::AsyncStdFs;
931 ///
932 /// let mut entries = AsyncStdFs::read_dir(".").await?;
933 ///
934 /// while let Some(res) = entries.next().await {
935 /// let entry = res?;
936 /// println!("{:?}", entry.path());
937 /// }
938 /// #
939 /// # Ok(()) }) }
940 /// ```
941 fn path(&self) -> PathBuf;
942
943 /// Returns the bare name of this entry without the leading path.
944 ///
945 /// # Examples
946 ///
947 /// Using the [`tokio`](https://docs.rs/tokio) runtime:
948 ///
949 /// ```no_run
950 /// # #[tokio::main]
951 /// # async fn main() -> std::io::Result<()> {
952 /// #
953 /// use futures::stream::StreamExt;
954 /// use fut_compat::fs::Filesystem;
955 /// use fut_compat::fs::TokioFs;
956 ///
957 /// let mut entries = TokioFs::read_dir(".").await?;
958 ///
959 /// while let Some(res) = entries.next().await {
960 /// let entry = res?;
961 /// println!("{}", entry.file_name().to_string_lossy());
962 /// }
963 /// #
964 /// # Ok(())
965 /// # }
966 /// ```
967 ///
968 /// Using the [`async_std`](https://docs.rs/async-std) runtime:
969 ///
970 /// ```no_run
971 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
972 /// #
973 /// use futures::stream::StreamExt;
974 /// use fut_compat::fs::Filesystem;
975 /// use fut_compat::fs::AsyncStdFs;
976 ///
977 /// let mut entries = AsyncStdFs::read_dir(".").await?;
978 ///
979 /// while let Some(res) = entries.next().await {
980 /// let entry = res?;
981 /// println!("{}", entry.file_name().to_string_lossy());
982 /// }
983 /// #
984 /// # Ok(()) }) }
985 /// ```
986 fn file_name(&self) -> OsString;
987
988 /// Reads the metadata for this entry.
989 ///
990 /// This function will traverse symbolic links to read the metadata.
991 ///
992 /// If you want to read metadata without following symbolic links, use [`symlink_metadata`]
993 /// instead.
994 ///
995 /// [`symlink_metadata`]: trait.Filesystem.html#tymethod.symlink_metadata
996 ///
997 /// # Errors
998 ///
999 /// An error will be returned in the following situations:
1000 ///
1001 /// * This entry does not point to an existing file or directory anymore.
1002 /// * The current process lacks permissions to read the metadata.
1003 /// * Some other I/O error occurred.
1004 ///
1005 /// # Examples
1006 ///
1007 /// Using the [`tokio`](https://docs.rs/tokio) runtime:
1008 ///
1009 /// ```no_run
1010 /// # #[tokio::main]
1011 /// # async fn main() -> std::io::Result<()> {
1012 /// #
1013 /// use futures::stream::StreamExt;
1014 /// use fut_compat::fs::Filesystem;
1015 /// use fut_compat::fs::TokioFs;
1016 ///
1017 /// let mut entries = TokioFs::read_dir(".").await?;
1018 ///
1019 /// while let Some(res) = entries.next().await {
1020 /// let entry = res?;
1021 /// println!("{:?}", entry.metadata().await?);
1022 /// }
1023 /// #
1024 /// # Ok(())
1025 /// # }
1026 /// ```
1027 ///
1028 /// Using the [`async_std`](https://docs.rs/async-std) runtime:
1029 ///
1030 /// ```no_run
1031 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
1032 /// #
1033 /// use futures::stream::StreamExt;
1034 /// use fut_compat::fs::Filesystem;
1035 /// use fut_compat::fs::AsyncStdFs;
1036 ///
1037 /// let mut entries = AsyncStdFs::read_dir(".").await?;
1038 ///
1039 /// while let Some(res) = entries.next().await {
1040 /// let entry = res?;
1041 /// println!("{:?}", entry.metadata().await?);
1042 /// }
1043 /// #
1044 /// # Ok(()) }) }
1045 /// ```
1046 async fn metadata(&self) -> std::io::Result<Metadata>;
1047
1048 /// Reads the file type for this entry.
1049 ///
1050 /// This function will not traverse symbolic links if this entry points at one.
1051 ///
1052 /// If you want to read metadata with following symbolic links, use [`metadata`] instead.
1053 ///
1054 /// [`metadata`]: #tymethod.metadata
1055 ///
1056 /// # Errors
1057 ///
1058 /// An error will be returned in the following situations:
1059 ///
1060 /// * This entry does not point to an existing file or directory anymore.
1061 /// * The current process lacks permissions to read this entry's metadata.
1062 /// * Some other I/O error occurred.
1063 ///
1064 /// # Examples
1065 ///
1066 /// Using the [`tokio`](https://docs.rs/tokio) runtime:
1067 ///
1068 /// ```no_run
1069 /// # #[tokio::main]
1070 /// # async fn main() -> std::io::Result<()> {
1071 /// #
1072 /// use futures::stream::StreamExt;
1073 /// use fut_compat::fs::Filesystem;
1074 /// use fut_compat::fs::TokioFs;
1075 ///
1076 /// let mut entries = TokioFs::read_dir(".").await?;
1077 ///
1078 /// while let Some(res) = entries.next().await {
1079 /// let entry = res?;
1080 /// println!("{:?}", entry.file_type().await?);
1081 /// }
1082 /// #
1083 /// # Ok(())
1084 /// # }
1085 /// ```
1086 ///
1087 /// Using the [`async_std`](https://docs.rs/async-std) runtime:
1088 ///
1089 /// ```no_run
1090 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
1091 /// #
1092 /// use futures::stream::StreamExt;
1093 /// use fut_compat::fs::Filesystem;
1094 /// use fut_compat::fs::AsyncStdFs;
1095 ///
1096 /// let mut entries = AsyncStdFs::read_dir(".").await?;
1097 ///
1098 /// while let Some(res) = entries.next().await {
1099 /// let entry = res?;
1100 /// println!("{:?}", entry.file_type().await?);
1101 /// }
1102 /// #
1103 /// # Ok(()) }) }
1104 /// ```
1105 async fn file_type(&self) -> std::io::Result<FileType>;
1106}
1107
1108
1109
1110/// An async abstraction over [`std::fs::File`].
1111#[async_trait]
1112pub trait File: Sized {
1113 /// Opens a file in read-only mode.
1114 ///
1115 /// See the [`OpenOptions::open`] function for more options.
1116 ///
1117 /// # Errors
1118 ///
1119 /// An error will be returned in the following situations:
1120 ///
1121 /// * `path` does not point to an existing file.
1122 /// * The current process lacks permissions to read the file.
1123 /// * Some other I/O error occurred.
1124 ///
1125 /// For more details, see the list of errors documented by [`OpenOptions::open`].
1126 ///
1127 /// [`OpenOptions::open`]: trait.OpenOptions.html#tymethod.open
1128 async fn open<P: AsRef<Path> + Send>(path: P) -> std::io::Result<Self>;
1129
1130 /// Opens a file in write-only mode.
1131 ///
1132 /// This function will create a file if it does not exist, and will truncate it if it does.
1133 ///
1134 /// See the [`OpenOptions::open`] function for more options.
1135 ///
1136 /// # Errors
1137 ///
1138 /// An error will be returned in the following situations:
1139 ///
1140 /// * The file's parent directory does not exist.
1141 /// * The current process lacks permissions to write to the file.
1142 /// * Some other I/O error occurred.
1143 ///
1144 /// For more details, see the list of errors documented by [`OpenOptions::open`].
1145 ///
1146 /// [`OpenOptions::open`]: trait.OpenOptions.html#tymethod.open
1147 async fn create<P: AsRef<Path> + Send>(path: P) -> std::io::Result<Self>;
1148
1149 /// Synchronizes OS-internal buffered contents and metadata to disk.
1150 ///
1151 /// This function will ensure that all in-memory data reaches the filesystem.
1152 ///
1153 /// This can be used to handle errors that would otherwise only be caught when the file is
1154 /// closed. When a file is dropped, errors in synchronizing this in-memory data are ignored.
1155 async fn sync_all(&self) -> std::io::Result<()>;
1156
1157 /// Synchronizes OS-internal buffered contents to disk.
1158 ///
1159 /// This is similar to [`sync_all`], except that file metadata may not be synchronized.
1160 ///
1161 /// This is intended for use cases that must synchronize the contents of the file, but don't
1162 /// need the file metadata synchronized to disk.
1163 ///
1164 /// Note that some platforms may simply implement this in terms of [`sync_all`].
1165 ///
1166 /// [`sync_all`]: #tymethod.sync_all
1167 async fn sync_data(&self) -> std::io::Result<()>;
1168
1169 /// Truncates or extends the file.
1170 ///
1171 /// If `size` is less than the current file size, then the file will be truncated. If it is
1172 /// greater than the current file size, then the file will be extended to `size` and have all
1173 /// intermediate data filled with zeros.
1174 ///
1175 /// The file's cursor stays at the same position, even if the cursor ends up being past the end
1176 /// of the file after this operation.
1177 async fn set_len(&self, size: u64) -> std::io::Result<()>;
1178
1179 /// Reads the file's metadata.
1180 async fn metadata(&self) -> std::io::Result<Metadata>;
1181
1182 /// Changes the permissions on the file.
1183 ///
1184 /// # Errors
1185 ///
1186 /// An error will be returned in the following situations:
1187 ///
1188 /// * The current process lacks permissions to change attributes on the file.
1189 /// * Some other I/O error occurred.
1190 async fn set_permissions(&self, perm: Permissions) -> std::io::Result<()>;
1191}
1192
1193/// An async abstraction over [`std::fs::OpenOptions`].
1194///
1195/// A builder for opening files with configurable options.
1196///
1197/// Files can be opened in [`read`] and/or [`write`] mode.
1198///
1199/// The [`append`] option opens files in a special writing mode that moves the file cursor to the
1200/// end of file before every write operation.
1201///
1202/// It is also possible to [`truncate`] the file right after opening, to [`create`] a file if it
1203/// doesn't exist yet, or to always create a new file with [`create_new`].
1204///
1205/// [`read`]: #tymethod.read
1206/// [`write`]: #tymethod.write
1207/// [`append`]: #tymethod.append
1208/// [`truncate`]: #tymethod.truncate
1209/// [`create`]: #tymethod.create
1210/// [`create_new`]: #tymethod.create_new
1211/// [`std::fs::OpenOptions`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html
1212///
1213/// # Examples
1214///
1215/// Open a file for reading using the [`tokio`](https://docs.rs/tokio) runtime:
1216///
1217/// ```no_run
1218/// # #[tokio::main]
1219/// # async fn main() -> std::io::Result<()> {
1220/// #
1221/// use tokio::fs::OpenOptions;
1222///
1223/// let file = OpenOptions::new()
1224/// .read(true)
1225/// .open("a.txt")
1226/// .await?;
1227/// #
1228/// # Ok(())
1229/// # }
1230/// ```
1231///
1232/// Open a file for reading using the [`async_std`](https://docs.rs/async-std) runtime:
1233///
1234/// ```no_run
1235/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
1236/// #
1237/// use async_std::fs::OpenOptions;
1238///
1239/// let file = OpenOptions::new()
1240/// .read(true)
1241/// .open("a.txt")
1242/// .await?;
1243/// #
1244/// # Ok(()) }) }
1245/// ```
1246///
1247/// Open a file for both reading and writing, and create it if it doesn't exist yet
1248/// using the [`tokio`](https://docs.rs/tokio) runtime:
1249///
1250/// ```no_run
1251/// # #[tokio::main]
1252/// # async fn main() -> std::io::Result<()> {
1253/// #
1254/// use tokio::fs::OpenOptions;
1255///
1256/// let file = OpenOptions::new()
1257/// .read(true)
1258/// .write(true)
1259/// .create(true)
1260/// .open("a.txt")
1261/// .await?;
1262/// #
1263/// # Ok(())
1264/// # }
1265/// ```
1266///
1267/// Open a file for both reading and writing, and create it if it doesn't exist yet
1268/// using the [`async_std`](https://docs.rs/async-std) runtime:
1269///
1270/// ```no_run
1271/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
1272/// #
1273/// use async_std::fs::OpenOptions;
1274///
1275/// let file = OpenOptions::new()
1276/// .read(true)
1277/// .write(true)
1278/// .create(true)
1279/// .open("a.txt")
1280/// .await?;
1281/// #
1282/// # Ok(()) }) }
1283/// ```
1284#[async_trait]
1285pub trait OpenOptions: Sized {
1286 /// The file object which gets returned by the [`open`](#tymethod.open) method.
1287 type File: File;
1288
1289 /// Creates a blank set of options.
1290 ///
1291 /// All options are initially set to `false`.
1292 fn new() -> Self;
1293
1294 /// Configures the option for read mode.
1295 ///
1296 /// When set to `true`, this option means the file will be readable after opening.
1297 fn read(&mut self, read: bool) -> &mut Self;
1298
1299 /// Configures the option for write mode.
1300 ///
1301 /// When set to `true`, this option means the file will be writable after opening.
1302 ///
1303 /// If the file already exists, write calls on it will overwrite the previous contents without
1304 /// truncating it.
1305 fn write(&mut self, write: bool) -> &mut Self;
1306
1307 /// Configures the option for append mode.
1308 ///
1309 /// When set to `true`, this option means the file will be writable after opening and the file
1310 /// cursor will be moved to the end of file before every write operaiton.
1311 fn append(&mut self, append: bool) -> &mut Self;
1312
1313 /// Configures the option for truncating the previous file.
1314 ///
1315 /// When set to `true`, the file will be truncated to the length of 0 bytes.
1316 ///
1317 /// The file must be opened in [`write`] or [`append`] mode for truncation to work.
1318 ///
1319 /// [`write`]: #tymethod.write
1320 /// [`append`]: #tymethod.append
1321 fn truncate(&mut self, truncate: bool) -> &mut Self;
1322
1323 /// Configures the option for creating a new file if it doesn't exist.
1324 ///
1325 /// When set to `true`, this option means a new file will be created if it doesn't exist.
1326 ///
1327 /// The file must be opened in [`write`] or [`append`] mode for file creation to work.
1328 ///
1329 /// [`write`]: #tymethod.write
1330 /// [`append`]: #tymethod.append
1331 fn create(&mut self, create: bool) -> &mut Self;
1332
1333 /// Configures the option for creating a new file or failing if it already exists.
1334 ///
1335 /// When set to `true`, this option means a new file will be created, or the open operation
1336 /// will fail if the file already exists.
1337 ///
1338 /// The file must be opened in [`write`] or [`append`] mode for file creation to work.
1339 ///
1340 /// [`write`]: #tymethod.write
1341 /// [`append`]: #tymethod.append
1342 fn create_new(&mut self, create_new: bool) -> &mut Self;
1343
1344 /// Opens a file with the configured options.
1345 ///
1346 /// # Errors
1347 ///
1348 /// An error will be returned in the following situations:
1349 ///
1350 /// * The file does not exist and neither [`create`] nor [`create_new`] were set.
1351 /// * The file's parent directory does not exist.
1352 /// * The current process lacks permissions to open the file in the configured mode.
1353 /// * The file already exists and [`create_new`] was set.
1354 /// * Invalid combination of options was used, like [`truncate`] was set but [`write`] wasn't,
1355 /// or none of [`read`], [`write`], and [`append`] modes was set.
1356 /// * An OS-level occurred, like too many files are open or the file name is too long.
1357 /// * Some other I/O error occurred.
1358 ///
1359 /// [`read`]: #tymethod.read
1360 /// [`write`]: #tymethod.write
1361 /// [`append`]: #tymethod.append
1362 /// [`truncate`]: #tymethod.truncate
1363 /// [`create`]: #tymethod.create
1364 /// [`create_new`]: #tymethod.create_new
1365 async fn open<P: AsRef<Path> + Send>(&self, path: P) -> std::io::Result<Self::File>;
1366}
1367
1368/// An async abstraction over [`std::fs::DirBuilder`].
1369#[async_trait]
1370pub trait DirBuilder: Sized {
1371 /// Creates a blank set of options.
1372 ///
1373 /// The [`recursive`] option is initially set to `false`.
1374 ///
1375 /// [`recursive`]: #tymethod.recursive
1376 fn new() -> Self;
1377
1378 /// Sets the option for recursive mode.
1379 ///
1380 /// When set to `true`, this option means all parent directories should be created recursively
1381 /// if they don't exist. Parents are created with the same permissions as the final directory.
1382 ///
1383 /// This option is initially set to `false`.
1384 fn recursive(&mut self, recursive: bool) -> &mut Self;
1385
1386 /// Creates a directory with the configured options.
1387 ///
1388 /// It is considered an error if the directory already exists unless recursive mode is enabled.
1389 async fn create<P: AsRef<Path> + Send>(&self, path: P) -> std::io::Result<()>;
1390}