use std::io::{self, Write};
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;
use std::path::Path;
use thiserror::Error;
use crate::verbatim_path;
#[derive(Debug)]
pub struct NamedTempFile(tempfile::NamedTempFile);
pub fn tempfile_in(path: &Path) -> io::Result<NamedTempFile> {
#[cfg(unix)]
let file = tempfile::Builder::new()
.permissions(std::fs::Permissions::from_mode(0o666))
.tempfile_in(path)?;
#[cfg(not(unix))]
let file = tempfile::Builder::new().tempfile_in(verbatim_path(path))?;
Ok(NamedTempFile(file))
}
impl NamedTempFile {
#[expect(clippy::disallowed_types, reason = "tempfile exposes a std::fs::File")]
pub fn as_file(&self) -> &std::fs::File {
self.0.as_file()
}
#[expect(clippy::disallowed_types, reason = "tempfile exposes a std::fs::File")]
pub fn persist(self, path: impl AsRef<Path>) -> Result<std::fs::File, PersistError> {
self.0
.persist(verbatim_path(path.as_ref()))
.map_err(|error| PersistError {
error: error.error,
file: Self(error.file),
})
}
}
impl AsRef<Path> for NamedTempFile {
fn as_ref(&self) -> &Path {
self.0.path()
}
}
impl Write for NamedTempFile {
fn write(&mut self, buffer: &[u8]) -> io::Result<usize> {
self.0.write(buffer)
}
fn flush(&mut self) -> io::Result<()> {
self.0.flush()
}
}
#[derive(Debug, Error)]
#[error("failed to persist temporary file: {error}")]
pub struct PersistError {
#[source]
pub error: io::Error,
pub file: NamedTempFile,
}