mod enumerate;
mod sys;
pub use self::enumerate::*;
use crate::io::ReadExt;
use std::fs::File;
use std::io::Write;
use std::path::Path;
pub fn file_exists(path: impl AsRef<Path>) -> bool {
match std::fs::metadata(path) {
Ok(meta) => meta.is_file(),
Err(_) => false,
}
}
pub fn directory_exists(path: impl AsRef<Path>) -> bool {
match std::fs::metadata(path) {
Ok(meta) => meta.is_dir(),
Err(_) => false,
}
}
pub fn read_all_bytes(path: impl AsRef<Path>) -> Result<Vec<u8>, std::io::Error> {
let mut file = File::open(path)?;
file.read_as_bytes()
}
pub fn write_all_bytes(path: impl AsRef<Path>, data: &[u8]) -> Result<(), std::io::Error> {
File::create(path).and_then(|mut file| file.write_all(data))
}
pub fn read_all_text(path: impl AsRef<Path>) -> Result<String, std::io::Error> {
let bytes = read_all_bytes(path)?;
String::from_utf8(bytes).map_err(|_| std::io::ErrorKind::InvalidData.into())
}
pub fn read_all_lines(path: impl AsRef<Path>) -> Result<Vec<String>, std::io::Error> {
let mut lines = read_all_text(path)?
.split('\n')
.map(|x| x.to_owned())
.collect::<Vec<_>>();
for line in &mut lines {
if line.ends_with('\r') {
line.pop();
}
}
Ok(lines)
}
pub fn write_all_text(path: impl AsRef<Path>, data: String) -> Result<(), std::io::Error> {
write_all_bytes(path, &data.into_bytes())
}
pub fn replace(
source: impl AsRef<Path>,
destination: impl AsRef<Path>,
backup: impl AsRef<Path>,
) -> Result<(), std::io::Error> {
let source = source.as_ref();
let destination = destination.as_ref();
let backup = backup.as_ref();
if crate::fs::file_exists(backup) {
std::fs::remove_file(backup)?;
}
if crate::fs::file_exists(destination) {
std::fs::rename(destination, backup)?;
}
match std::fs::rename(source, destination) {
Ok(()) => {
std::fs::remove_file(backup).ok();
Ok(())
}
Err(e) => {
std::fs::rename(backup, source).ok();
Err(e)
}
}
}
pub trait FileExt {
fn allocation_size(&self) -> Result<u64, std::io::Error>;
fn set_allocation_size(&self, length: u64) -> Result<(), std::io::Error>;
}
impl FileExt for File {
fn allocation_size(&self) -> Result<u64, std::io::Error> {
crate::fs::sys::get_allocation_size(self)
}
fn set_allocation_size(&self, length: u64) -> Result<(), std::io::Error> {
crate::fs::sys::set_allocation_size(self, length)
}
}
#[derive(Clone, Debug)]
pub struct VolumeInformation {
pub free_bytes: u64,
pub available_bytes: u64,
pub total_bytes: u64,
pub allocation_granularity: u64,
}
pub fn get_volume_information(path: impl AsRef<Path>) -> Result<VolumeInformation, std::io::Error> {
crate::fs::sys::get_volume_information(path.as_ref())
}
pub fn volume_free_bytes(path: impl AsRef<Path>) -> Result<u64, std::io::Error> {
get_volume_information(path).map(|x| x.free_bytes)
}
pub fn volume_available_bytes(path: impl AsRef<Path>) -> Result<u64, std::io::Error> {
get_volume_information(path).map(|x| x.available_bytes)
}
pub fn volume_total_bytes(path: impl AsRef<Path>) -> Result<u64, std::io::Error> {
get_volume_information(path).map(|x| x.total_bytes)
}
pub fn allocation_granularity(path: impl AsRef<Path>) -> Result<u64, std::io::Error> {
get_volume_information(path).map(|x| x.allocation_granularity)
}