use smol::{fs, io};
use std::path::{Path, PathBuf};
use std::{fmt::Debug, iter::FusedIterator};
mod signed_duration;
pub(crate) use signed_duration::*;
const SANITIZE_FILE_NAME_OPTIONS: sanitise_file_name::Options<Option<char>> =
sanitise_file_name::Options {
normalise_whitespace: false,
replace_with: None,
..sanitise_file_name::Options::DEFAULT
};
pub trait UnsizedIter<T>: Iterator<Item = T> + FusedIterator + Clone + Debug {}
impl<I, T> UnsizedIter<T> for I where I: Iterator<Item = T> + FusedIterator + Clone + Debug {}
pub trait Iter<T>: UnsizedIter<T> + ExactSizeIterator {}
impl<I, T> Iter<T> for I where I: UnsizedIter<T> + ExactSizeIterator {}
pub(crate) async fn write_file_atomic(
path: impl AsRef<Path>,
contents: impl AsRef<[u8]>,
) -> Result<(), io::Error> {
let path = path.as_ref();
let mut tmp_path = PathBuf::from(path);
tmp_path.pop();
let mut tmp_basename = path
.file_stem()
.unwrap_or_else(|| {
panic!(
"write_file_atomic path must have a basename, was {:?}",
path
)
})
.to_owned();
tmp_basename.push(format!("-tmp-{:0}", rand::random::<u32>()));
if let Some(ext) = path.extension() {
tmp_basename.push(ext);
}
tmp_path.push(tmp_basename);
fs::write(&tmp_path, contents).await?;
fs::rename(tmp_path, path).await?;
Ok(())
}
pub(crate) fn sanitize_file_name(name: impl AsRef<str>) -> String {
sanitise_file_name::sanitise_with_options(name.as_ref(), &SANITIZE_FILE_NAME_OPTIONS)
}