1use std::path::{
4 Path,
5 PathBuf,
6};
7
8use crate::{
9 AsyncFile,
10 FsError,
11 Operation,
12};
13
14pub struct TempDir {
16 path: PathBuf,
17}
18
19impl TempDir {
20 pub async fn create(root: impl AsRef<Path>) -> Result<Self, FsError> {
22 let root = root.as_ref().to_owned();
23 tokio::fs::create_dir_all(&root)
24 .await
25 .map_err(|error| FsError::io(Operation::Directory, &root, error))?;
26 let path = root.join(format!("tmp-{}", uuid::Uuid::new_v4()));
27 tokio::fs::create_dir(&path)
28 .await
29 .map_err(|error| FsError::io(Operation::Directory, &path, error))?;
30 Ok(Self { path })
31 }
32
33 #[must_use]
35 pub fn path(&self) -> &Path {
36 &self.path
37 }
38
39 pub async fn remove(self) -> Result<(), FsError> {
41 crate::directory::remove_dir_all(&self.path).await
42 }
43}
44
45pub struct TempFile {
47 path: PathBuf,
48 file: Option<AsyncFile>,
49}
50
51impl TempFile {
52 pub async fn create(root: impl AsRef<Path>) -> Result<Self, FsError> {
54 let root = root.as_ref().to_owned();
55 tokio::fs::create_dir_all(&root)
56 .await
57 .map_err(|error| FsError::io(Operation::Directory, &root, error))?;
58 let path = root.join(format!("tmp-file-{}", uuid::Uuid::new_v4()));
59 let file = AsyncFile::create_new(&path).await?;
60 Ok(Self {
61 path,
62 file: Some(file),
63 })
64 }
65
66 #[must_use]
68 pub fn path(&self) -> &Path {
69 &self.path
70 }
71
72 pub fn file_mut(&mut self) -> Result<&mut AsyncFile, FsError> {
74 self.file.as_mut().ok_or_else(|| {
75 FsError::InvalidRequest("temporary file handle was already closed".to_owned())
76 })
77 }
78
79 pub async fn remove(mut self) -> Result<(), FsError> {
81 self.file.take();
82 tokio::fs::remove_file(&self.path)
83 .await
84 .map_err(|error| FsError::io(Operation::Write, &self.path, error))
85 }
86
87 pub fn persist(mut self) -> PathBuf {
89 self.file.take();
90 self.path
91 }
92}