You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lolistealer/src/tempfile.rs

95 lines
1.9 KiB

use std::{
ops,
path::{
PathBuf,
Path
},
fmt,
};
use lazy_static::lazy_static;
pub mod error;
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct TempFile(PathBuf);
const FILENAME_LEN_BYTES: usize = 16;
const PREFIX: &'static str = "lolistealer-";
lazy_static! {
pub static ref LOCATION: &'static Path = {
Box::leak(std::env::temp_dir().into_boxed_path())
};
}
/// Generate a new random byte string for a filename.
fn generate_filename(mut to: impl fmt::Write) -> Result<(), error::Error>
{
let mut buffer = [0u8; FILENAME_LEN_BYTES];
getrandom::getrandom(&mut buffer[..])?;
write!(to, "{}", PREFIX)?;
for byte in buffer.iter() {
write!(to, "{:02x}", *byte)?;
}
Ok(())
}
impl TempFile
{
/// Create a new temp file path
pub fn new() -> Self
{
let mut buffer = String::with_capacity((FILENAME_LEN_BYTES*2) + PREFIX.len());
generate_filename(&mut buffer).expect("tf fatal");
Self(LOCATION.join(buffer))
}
/// Try to create a new temp file path
pub fn try_new() -> Result<Self, error::Error>
{
let mut buffer = String::with_capacity((FILENAME_LEN_BYTES*2) + PREFIX.len());
generate_filename(&mut buffer)?;
Ok(Self(LOCATION.join(buffer)))
}
/// Consume the `TempFile` and return the raw path, performing no cleanup.
pub fn into_pathbuf(mut self) -> PathBuf
{
let pb = std::mem::replace(&mut self.0, PathBuf::default());
std::mem::forget(self);
pb
}
}
impl ops::Drop for TempFile
{
fn drop(&mut self)
{
if self.0.exists() {
if self.0.is_file() {
let _ = std::fs::remove_file(&self.0);
} else {
let _ = std::fs::remove_dir_all(&self.0);
}
}
}
}
impl AsRef<Path> for TempFile
{
fn as_ref(&self) -> &Path
{
self.0.as_ref()
}
}
impl ops::Deref for TempFile
{
type Target = Path;
fn deref(&self) -> &Self::Target
{
self.0.as_ref()
}
}