use std::fs::File;
use std::io::{BufRead, BufReader, BufWriter, Read, Write};
use std::path::Path;
use crate::error::{CoreError, CoreResult};
pub fn open_file<P: AsRef<Path>>(path: P) -> CoreResult<BufReader<File>> {
let file = File::open(path.as_ref()).map_err(CoreError::IoError)?;
Ok(BufReader::new(file))
}
pub fn create_file<P: AsRef<Path>>(path: P) -> CoreResult<BufWriter<File>> {
let file = File::create(path.as_ref()).map_err(CoreError::IoError)?;
Ok(BufWriter::new(file))
}
pub fn read_to_string<P: AsRef<Path>>(path: P) -> CoreResult<String> {
let mut file = open_file(path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)
.map_err(CoreError::IoError)?;
Ok(contents)
}
pub fn read_to_bytes<P: AsRef<Path>>(path: P) -> CoreResult<Vec<u8>> {
let mut file = open_file(path)?;
let mut contents = Vec::new();
file.read_to_end(&mut contents)
.map_err(CoreError::IoError)?;
Ok(contents)
}
pub fn write_string<P: AsRef<Path>, S: AsRef<str>>(path: P, contents: S) -> CoreResult<()> {
let mut file = create_file(path)?;
file.write_all(contents.as_ref().as_bytes())
.map_err(CoreError::IoError)?;
file.flush().map_err(CoreError::IoError)?;
Ok(())
}
pub fn write_bytes<P: AsRef<Path>, B: AsRef<[u8]>>(path: P, contents: B) -> CoreResult<()> {
let mut file = create_file(path)?;
file.write_all(contents.as_ref())
.map_err(CoreError::IoError)?;
file.flush().map_err(CoreError::IoError)?;
Ok(())
}
pub fn read_lines<P, F>(path: P, mut callback: F) -> CoreResult<()>
where
P: AsRef<Path>,
F: FnMut(String) -> CoreResult<()>,
{
let file = open_file(path)?;
for line in file.lines() {
let line = line.map_err(CoreError::IoError)?;
callback(line)?;
}
Ok(())
}
pub fn file_exists<P: AsRef<Path>>(path: P) -> bool {
path.as_ref().exists() && path.as_ref().is_file()
}
pub fn directory_exists<P: AsRef<Path>>(path: P) -> bool {
path.as_ref().exists() && path.as_ref().is_dir()
}
pub fn create_directory<P: AsRef<Path>>(path: P) -> CoreResult<()> {
if !directory_exists(&path) {
std::fs::create_dir_all(path.as_ref()).map_err(CoreError::IoError)?;
}
Ok(())
}
pub fn file_size<P: AsRef<Path>>(path: P) -> CoreResult<u64> {
let metadata = std::fs::metadata(path.as_ref()).map_err(CoreError::IoError)?;
Ok(metadata.len())
}
pub fn format_file_size(size: u64) -> String {
const KB: u64 = 1024;
const MB: u64 = KB * 1024;
const GB: u64 = MB * 1024;
const TB: u64 = GB * 1024;
if size >= TB {
format!("{:.2} TB", size as f64 / TB as f64)
} else if size >= GB {
format!("{:.2} GB", size as f64 / GB as f64)
} else if size >= MB {
format!("{:.2} MB", size as f64 / MB as f64)
} else if size >= KB {
format!("{:.2} KB", size as f64 / KB as f64)
} else {
format!("{} B", size)
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Write;
use tempfile::tempdir;
#[test]
fn test_read_write_string() {
let dir = tempdir().unwrap();
let file_path = dir.path().join("test.txt");
let test_str = "Hello, world!";
write_string(&file_path, test_str).unwrap();
let contents = read_to_string(&file_path).unwrap();
assert_eq!(contents, test_str);
}
#[test]
fn test_read_write_bytes() {
let dir = tempdir().unwrap();
let file_path = dir.path().join("test.bin");
let test_bytes = vec![1, 2, 3, 4, 5];
write_bytes(&file_path, &test_bytes).unwrap();
let contents = read_to_bytes(&file_path).unwrap();
assert_eq!(contents, test_bytes);
}
#[test]
fn test_read_lines() {
let dir = tempdir().unwrap();
let file_path = dir.path().join("test_lines.txt");
{
let mut file = File::create(&file_path).unwrap();
writeln!(file, "Line 1").unwrap();
writeln!(file, "Line 2").unwrap();
writeln!(file, "Line 3").unwrap();
}
let mut lines = Vec::new();
read_lines(&file_path, |line| {
lines.push(line);
Ok(())
})
.unwrap();
assert_eq!(lines, vec!["Line 1", "Line 2", "Line 3"]);
}
#[test]
fn test_file_exists() {
let dir = tempdir().unwrap();
let file_path = dir.path().join("test_exists.txt");
assert!(!file_exists(&file_path));
File::create(&file_path).unwrap();
assert!(file_exists(&file_path));
}
#[test]
fn test_directory_exists() {
let dir = tempdir().unwrap();
let dir_path = dir.path().join("test_dir");
assert!(!directory_exists(&dir_path));
std::fs::create_dir(&dir_path).unwrap();
assert!(directory_exists(&dir_path));
}
#[test]
fn test_create_directory() {
let dir = tempdir().unwrap();
let dir_path = dir.path().join("test_create_dir");
assert!(!directory_exists(&dir_path));
create_directory(&dir_path).unwrap();
assert!(directory_exists(&dir_path));
}
#[test]
fn test_file_size() {
let dir = tempdir().unwrap();
let file_path = dir.path().join("test_size.txt");
let test_str = "Hello, world!";
write_string(&file_path, test_str).unwrap();
let size = file_size(&file_path).unwrap();
assert_eq!(size, test_str.len() as u64);
}
#[test]
fn test_format_file_size() {
assert_eq!(format_file_size(500), "500 B");
assert_eq!(format_file_size(1024), "1.00 KB");
assert_eq!(format_file_size(1500), "1.46 KB");
assert_eq!(format_file_size(1024 * 1024), "1.00 MB");
assert_eq!(format_file_size(1024 * 1024 * 1024), "1.00 GB");
assert_eq!(format_file_size(1024 * 1024 * 1024 * 1024), "1.00 TB");
}
}