use crate::{WallSwitchError, WallSwitchResult};
use std::{fmt::Debug, fs, path::Path};
pub trait AtomicWriteExt {
fn atomic_write<F>(&self, write_fn: F) -> WallSwitchResult<()>
where
F: FnOnce(&Path) -> WallSwitchResult<()>;
}
impl AtomicWriteExt for Path {
fn atomic_write<F>(&self, write_fn: F) -> WallSwitchResult<()>
where
F: FnOnce(&Path) -> WallSwitchResult<()>,
{
let temp_ext = format!("tmp-{}", std::process::id());
let temp_path = self.with_extension(temp_ext);
if let Some(parent) = self.parent() {
fs::create_dir_all(parent).map_err(|e| WallSwitchError::IOError {
path: parent.to_path_buf(),
io_error: e,
})?;
}
let write_res = write_fn(&temp_path);
if let Err(err) = write_res {
let _ = fs::remove_file(&temp_path);
return Err(err);
}
fs::rename(&temp_path, self).map_err(|io_error| {
let _ = fs::remove_file(&temp_path);
WallSwitchError::IOError {
path: self.to_path_buf(),
io_error,
}
})?;
Ok(())
}
}
pub trait ConcurrencyExt {
fn get_optimal_cores(&self) -> usize {
rayon::current_num_threads()
}
fn get_chunk_size(&self, total_len: usize) -> usize {
(total_len / self.get_optimal_cores()).max(1)
}
}
impl<T> ConcurrencyExt for [T] {}
pub trait DigitWidth {
fn digit_width(&self) -> usize;
}
impl DigitWidth for usize {
fn digit_width(&self) -> usize {
self.checked_ilog10().map_or(1, |n| (n + 1) as usize)
}
}
impl DigitWidth for u64 {
fn digit_width(&self) -> usize {
self.checked_ilog10().map_or(1, |n| (n + 1) as usize)
}
}
pub trait PrintWithSpaces {
fn print_with_spaces(&self, spaces: &str);
}
impl<T> PrintWithSpaces for [T]
where
T: Debug,
{
fn print_with_spaces(&self, spaces: &str) {
for item in self {
println!("{spaces}{item:?}");
}
}
}
pub trait FloatIterExt {
fn float_min(&mut self) -> f64;
fn float_max(&mut self) -> f64;
}
impl<T> FloatIterExt for T
where
T: Iterator<Item = f64>,
{
fn float_max(&mut self) -> f64 {
self.fold(f64::NAN, f64::max)
}
fn float_min(&mut self) -> f64 {
self.fold(f64::NAN, f64::min)
}
}
pub trait IntegerIterExt {
fn integer_min(&mut self) -> u32;
fn integer_max(&mut self) -> u32;
}
impl<T> IntegerIterExt for T
where
T: Iterator<Item = u32>,
{
fn integer_max(&mut self) -> u32 {
self.fold(u32::MIN, u32::max)
}
fn integer_min(&mut self) -> u32 {
self.fold(u32::MAX, u32::min)
}
}
pub trait U8Extension {
fn to_usize(self) -> usize;
fn to_u64(self) -> u64;
}
impl U8Extension for u8 {
fn to_usize(self) -> usize {
Into::<usize>::into(self)
}
fn to_u64(self) -> u64 {
Into::<u64>::into(self)
}
}