use super::NamedWriteError;
use std::{fs, path::Path};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum PublicationMode {
Replace,
CreateNew,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct WriteOptions {
pub mode: PublicationMode,
pub permissions: u32,
}
pub fn write_with<T, E>(
path: &Path,
options: WriteOptions,
produce: impl FnOnce(&mut fs::File) -> Result<T, E>,
) -> Result<T, NamedWriteError<E>> {
#[cfg(any(target_os = "linux", target_os = "android", target_vendor = "apple"))]
{
super::supported::commit_path_with_options(
path,
options,
|_, file| produce(file),
None::<(bool, fn(&Path, &T) -> Result<(), E>)>,
|_, _| Ok(()),
)
}
#[cfg(not(any(target_os = "linux", target_os = "android", target_vendor = "apple")))]
{
let _ = (path, options, produce);
Err(NamedWriteError::before(std::io::Error::new(
std::io::ErrorKind::Unsupported,
"durable atomic file publication is unsupported",
)))
}
}
#[cfg(unix)]
pub fn write_at_with<T, E>(
parent: std::os::fd::BorrowedFd<'_>,
name: &std::ffi::OsStr,
options: WriteOptions,
produce: impl FnOnce(&mut fs::File) -> Result<T, E>,
) -> Result<T, NamedWriteError<E>> {
#[cfg(any(target_os = "linux", target_os = "android", target_vendor = "apple"))]
{
super::supported::commit_at_with_hook(
parent,
None,
name,
options,
|_, file| produce(file),
None::<(bool, fn(&Path, &T) -> Result<(), E>)>,
|_, _| Ok(()),
)
}
#[cfg(not(any(target_os = "linux", target_os = "android", target_vendor = "apple")))]
{
let _ = (parent, name, options, produce);
Err(NamedWriteError::before(std::io::Error::new(
std::io::ErrorKind::Unsupported,
"durable atomic file publication is unsupported",
)))
}
}
#[cfg(unix)]
pub fn write_at_validated_with<T, E>(
parent: std::os::fd::BorrowedFd<'_>,
name: &std::ffi::OsStr,
options: WriteOptions,
produce: impl FnOnce(&mut fs::File) -> Result<T, E>,
admit: impl FnOnce(&T) -> Result<(), E>,
) -> Result<T, NamedWriteError<E>> {
#[cfg(any(target_os = "linux", target_os = "android", target_vendor = "apple"))]
{
super::supported::commit_at_with_hook(
parent,
None,
name,
options,
|_, file| produce(file),
Some((false, |_: &Path, value: &T| admit(value))),
|_, _| Ok(()),
)
}
#[cfg(not(any(target_os = "linux", target_os = "android", target_vendor = "apple")))]
{
let _ = (parent, name, options, produce, admit);
Err(NamedWriteError::before(std::io::Error::new(
std::io::ErrorKind::Unsupported,
"durable atomic file publication is unsupported",
)))
}
}
pub fn write_validated_with<T, E>(
path: &Path,
options: WriteOptions,
produce: impl FnOnce(&mut fs::File) -> Result<T, E>,
admit: impl FnOnce(&Path, &T) -> Result<(), E>,
) -> Result<T, NamedWriteError<E>> {
#[cfg(any(target_os = "linux", target_os = "android", target_vendor = "apple"))]
{
super::supported::validate_target_path(path).map_err(NamedWriteError::before)?;
let absolute = std::path::absolute(path).map_err(NamedWriteError::before)?;
super::supported::commit_path_with_options(
&absolute,
options,
|_, file| produce(file),
Some((true, admit)),
|_, _| Ok(()),
)
}
#[cfg(not(any(target_os = "linux", target_os = "android", target_vendor = "apple")))]
{
let _ = (path, options, produce, admit);
Err(NamedWriteError::before(std::io::Error::new(
std::io::ErrorKind::Unsupported,
"durable atomic file publication is unsupported",
)))
}
}
#[cfg(all(
test,
any(target_os = "linux", target_os = "android", target_vendor = "apple")
))]
mod tests;