use std::io::Write;
use std::path::{Path, PathBuf};
pub const PAYLOAD_PREFIX: &str = ".tmp";
pub const PAYLOAD_RAND_LEN: usize = 6;
pub fn payload_dir() -> PathBuf {
absolute_temp_dir(std::env::temp_dir())
}
fn absolute_temp_dir(dir: PathBuf) -> PathBuf {
if dir.is_absolute() {
dir
} else {
PathBuf::from("/tmp")
}
}
pub fn create_payload(dir: &Path, data: &str) -> std::io::Result<tempfile::TempPath> {
let mut tmp = tempfile::Builder::new()
.prefix(PAYLOAD_PREFIX)
.rand_bytes(PAYLOAD_RAND_LEN)
.tempfile_in(dir)?;
tmp.write_all(data.as_bytes())?;
Ok(tmp.into_temp_path())
}
pub fn is_payload_shaped(path: &Path, dir: &Path) -> bool {
let Some(name) = path.file_name().and_then(|n| n.to_str()) else {
return false;
};
path.parent() == Some(dir)
&& name.strip_prefix(PAYLOAD_PREFIX).is_some_and(|rand| {
rand.len() == PAYLOAD_RAND_LEN && rand.bytes().all(|b| b.is_ascii_alphanumeric())
})
}
pub fn remove_payload(path: &Path) -> std::io::Result<()> {
match std::fs::remove_file(path) {
Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(()),
other => other,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn absolute_temp_dir_falls_back_to_tmp_when_empty_or_relative() {
assert_eq!(absolute_temp_dir(PathBuf::new()), PathBuf::from("/tmp"));
assert_eq!(
absolute_temp_dir(PathBuf::from("relative/dir")),
PathBuf::from("/tmp")
);
}
#[test]
fn absolute_temp_dir_keeps_absolute_dir() {
let dir = PathBuf::from("/some/abs/tmp");
assert_eq!(absolute_temp_dir(dir.clone()), dir);
}
#[test]
fn payload_from_producer_is_accepted_by_consumer() {
let dir = tempfile::TempDir::new().unwrap();
let payload = create_payload(dir.path(), "{}").unwrap();
assert!(is_payload_shaped(&payload, dir.path()));
}
#[test]
fn is_payload_shaped_accepts_tmp_file_in_payload_dir() {
let dir = PathBuf::from("/some/tmp");
assert!(is_payload_shaped(&dir.join(".tmpAbC123"), &dir));
}
#[test]
fn is_payload_shaped_rejects_other_names_and_dirs() {
let dir = PathBuf::from("/some/tmp");
assert!(!is_payload_shaped(&dir.join("payload.json"), &dir));
assert!(!is_payload_shaped(&dir.join(".tmpBadJson"), &dir));
assert!(!is_payload_shaped(
&PathBuf::from("/elsewhere/.tmpAbC123"),
&dir
));
assert!(!is_payload_shaped(
&dir.join("nested").join(".tmpAbC123"),
&dir
));
}
}