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