use std::fs::{metadata, Metadata};
use std::path::{Path, PathBuf};
use std::io::Result;
use sha2::{Digest, Sha256};
pub struct File {
path: PathBuf,
}
impl File {
pub fn new<P: AsRef<Path>>(path: P) -> Self {
File {
path: path.as_ref().to_path_buf(),
}
}
pub fn metadata(&self) -> Result<Metadata> {
metadata(&self.path)
}
pub fn len(&self) -> i64 {
match self.metadata() {
Ok(meta) => meta.len() as i64,
Err(_) => -1,
}
}
pub fn hash(&self) -> String {
if !self.is_file() {
return String::new();
}
match std::fs::read(&self.path) {
Ok(content) => {
let mut hasher = Sha256::new();
hasher.update(content);
let result = hasher.finalize();
format!("{:x}", result)
}
Err(_) => String::new(),
}
}
pub fn is_match(&self, other: &File) -> bool {
self.hash() == other.hash()
}
pub fn is_file(&self) -> bool {
self.path.is_file()
}
pub fn is_directory(&self) -> bool {
self.path.is_dir()
}
pub fn exists(&self) -> bool {
self.path.exists()
}
pub fn rm(&self) -> Result<()> {
if self.is_file() {
std::fs::remove_file(&self.path)?;
} else if self.is_directory() {
std::fs::remove_dir_all(&self.path)?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
fn setup_test_env(test_name: &str) -> PathBuf {
let temp_dir = std::env::temp_dir().join("files_test").join(test_name);
if temp_dir.exists() {
fs::remove_dir_all(&temp_dir).unwrap();
}
fs::create_dir_all(&temp_dir).unwrap();
temp_dir
}
#[test]
fn test_file_creation_and_checks() {
let test_dir = setup_test_env("test_file_creation_and_checks");
let file_path = test_dir.join("test_file.txt");
let dir_path = test_dir.join("test_dir");
fs::File::create(&file_path).unwrap();
fs::create_dir(&dir_path).unwrap();
let file = File::new(&file_path);
let dir = File::new(&dir_path);
let non_existent = File::new("non_existent_file.txt");
assert!(file.exists());
assert!(file.is_file());
assert!(!file.is_directory());
assert!(dir.exists());
assert!(dir.is_directory());
assert!(!dir.is_file());
assert!(!non_existent.exists());
}
#[test]
fn test_rm_file() {
let test_dir = setup_test_env("test_rm_file");
let file_path = test_dir.join("file_to_delete.txt");
fs::File::create(&file_path).unwrap();
let file = File::new(&file_path);
assert!(file.exists());
file.rm().unwrap();
assert!(!file.exists());
}
#[test]
fn test_rm_dir() {
let test_dir = setup_test_env("test_rm_dir");
let dir_path = test_dir.join("dir_to_delete");
fs::create_dir_all(&dir_path).unwrap();
fs::File::create(dir_path.join("inner_file.txt")).unwrap();
let dir = File::new(&dir_path);
assert!(dir.exists());
dir.rm().unwrap();
assert!(!dir.exists());
}
#[test]
fn test_rm_non_existent() {
let non_existent_file = File::new("path/that/does/not/exist.tmp");
assert!(non_existent_file.rm().is_ok());
}
}