use std::fs;
use std::path::{Path, PathBuf};
use teaql_tool_core::{Result, TeaQLToolError};
pub struct FileTool;
impl FileTool {
pub fn read_string<P: AsRef<Path>>(&self, path: P) -> Result<String> {
fs::read_to_string(path.as_ref())
.map_err(|e| TeaQLToolError::ExecutionError(format!("Failed to read file: {}", e)))
}
pub fn read_bytes<P: AsRef<Path>>(&self, path: P) -> Result<Vec<u8>> {
fs::read(path.as_ref())
.map_err(|e| TeaQLToolError::ExecutionError(format!("Failed to read bytes: {}", e)))
}
pub fn write_string<P: AsRef<Path>, C: AsRef<[u8]>>(&self, path: P, content: C) -> Result<()> {
fs::write(path.as_ref(), content)
.map_err(|e| TeaQLToolError::ExecutionError(format!("Failed to write file: {}", e)))
}
pub fn exists<P: AsRef<Path>>(&self, path: P) -> bool {
path.as_ref().exists()
}
pub fn is_file<P: AsRef<Path>>(&self, path: P) -> bool {
path.as_ref().is_file()
}
pub fn is_dir<P: AsRef<Path>>(&self, path: P) -> bool {
path.as_ref().is_dir()
}
pub fn mkdir<P: AsRef<Path>>(&self, path: P) -> Result<()> {
fs::create_dir(path.as_ref())
.map_err(|e| TeaQLToolError::ExecutionError(format!("Failed to create directory: {}", e)))
}
pub fn mkdir_all<P: AsRef<Path>>(&self, path: P) -> Result<()> {
fs::create_dir_all(path.as_ref())
.map_err(|e| TeaQLToolError::ExecutionError(format!("Failed to create directories recursively: {}", e)))
}
pub fn delete_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
fs::remove_file(path.as_ref())
.map_err(|e| TeaQLToolError::ExecutionError(format!("Failed to delete file: {}", e)))
}
pub fn delete_dir<P: AsRef<Path>>(&self, path: P) -> Result<()> {
fs::remove_dir(path.as_ref())
.map_err(|e| TeaQLToolError::ExecutionError(format!("Failed to delete directory: {}", e)))
}
pub fn delete_recursive<P: AsRef<Path>>(&self, path: P) -> Result<()> {
fs::remove_dir_all(path.as_ref())
.map_err(|e| TeaQLToolError::ExecutionError(format!("Failed to recursively delete directory: {}", e)))
}
pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(&self, from: P, to: Q) -> Result<u64> {
fs::copy(from.as_ref(), to.as_ref())
.map_err(|e| TeaQLToolError::ExecutionError(format!("Failed to copy file: {}", e)))
}
pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(&self, from: P, to: Q) -> Result<()> {
fs::rename(from.as_ref(), to.as_ref())
.map_err(|e| TeaQLToolError::ExecutionError(format!("Failed to rename/move: {}", e)))
}
pub fn list_files<P: AsRef<Path>>(&self, dir: P) -> Result<Vec<PathBuf>> {
self.list_entries(dir, true, false)
}
pub fn list_dirs<P: AsRef<Path>>(&self, dir: P) -> Result<Vec<PathBuf>> {
self.list_entries(dir, false, true)
}
fn list_entries<P: AsRef<Path>>(&self, dir: P, include_files: bool, include_dirs: bool) -> Result<Vec<PathBuf>> {
let mut result = Vec::new();
let entries = fs::read_dir(dir.as_ref())
.map_err(|e| TeaQLToolError::ExecutionError(format!("Failed to read directory: {}", e)))?;
for entry in entries {
let entry = entry.map_err(|e| TeaQLToolError::ExecutionError(format!("Error reading directory entry: {}", e)))?;
let path = entry.path();
if path.is_file() && include_files {
result.push(path);
} else if path.is_dir() && include_dirs {
result.push(path);
}
}
Ok(result)
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::env;
#[test]
fn test_file_operations() {
let tool = FileTool;
let mut tmp_path = env::temp_dir();
tmp_path.push("teaql_test_file.txt");
tool.write_string(&tmp_path, "hello teaql").unwrap();
assert!(tool.exists(&tmp_path));
assert!(tool.is_file(&tmp_path));
let content = tool.read_string(&tmp_path).unwrap();
assert_eq!(content, "hello teaql");
tool.delete_file(&tmp_path).unwrap();
assert!(!tool.exists(&tmp_path));
}
}