1#![forbid(unsafe_code)]
9
10use rand::RngCore;
11use std::{
12 fs, io,
13 path::{Path, PathBuf},
14};
15
16#[derive(Debug, PartialEq)]
20pub struct TempPath {
21 path_buf: PathBuf,
22 persist: bool,
23}
24
25impl Drop for TempPath {
26 fn drop(&mut self) {
27 if !self.persist {
28 fs::remove_dir_all(&self.path_buf)
29 .or_else(|_| fs::remove_file(&self.path_buf))
30 .unwrap_or(());
31 }
32 }
33}
34
35impl TempPath {
36 pub fn new() -> Self { Self::new_with_temp_dir(std::env::temp_dir()) }
38
39 pub fn new_with_temp_dir(temp_dir: PathBuf) -> Self {
41 let mut temppath = temp_dir;
42 let mut rng = rand::thread_rng();
43 let mut bytes = [0_u8; 16];
44 rng.fill_bytes(&mut bytes);
45 temppath.push(hex::encode(&bytes));
46
47 TempPath {
48 path_buf: temppath,
49 persist: false,
50 }
51 }
52
53 pub fn path(&self) -> &Path { &self.path_buf }
55
56 pub fn persist(&mut self) { self.persist = true; }
58
59 pub fn create_as_file(&self) -> io::Result<()> {
60 let mut builder = fs::OpenOptions::new();
61 builder.write(true).create_new(true);
62 builder.open(self.path())?;
63 Ok(())
64 }
65
66 pub fn create_as_dir(&self) -> io::Result<()> {
67 let builder = fs::DirBuilder::new();
68 builder.create(self.path())?;
69 Ok(())
70 }
71}
72
73impl std::convert::AsRef<Path> for TempPath {
74 fn as_ref(&self) -> &Path { self.path() }
75}
76
77impl Default for TempPath {
78 fn default() -> Self { Self::new() }
79}