use std::fs::File;
use std::io::{self, Read, Write};
use std::path::Path;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum ProcessError {
#[error("Failed to read file: {0}")]
ReadError(io::Error),
#[error("Failed to write to file: {0}")]
WriteError(io::Error),
#[error("Failed to process content: {0}")]
ContentError(String),
#[error("Invalid path: {0}")]
InvalidPath(String),
}
pub fn read_content<P: AsRef<Path>>(
path: P,
) -> Result<String, ProcessError> {
let path_ref = path.as_ref();
if !path_ref.exists() {
return Err(ProcessError::InvalidPath(format!(
"Path does not exist: {}",
path_ref.display()
)));
}
let mut file =
File::open(path_ref).map_err(ProcessError::ReadError)?;
let mut content = String::new();
let _ = file
.read_to_string(&mut content)
.map_err(ProcessError::ReadError)?;
Ok(content)
}
pub fn write_content<P: AsRef<Path>>(
path: P,
content: &str,
) -> Result<(), ProcessError> {
let path_ref = path.as_ref();
let mut file =
File::create(path_ref).map_err(ProcessError::WriteError)?;
file.write_all(content.as_bytes())
.map_err(ProcessError::WriteError)
}
pub fn process_content<F>(
content: &str,
transform_fn: F,
) -> Result<String, ProcessError>
where
F: Fn(&str) -> Result<String, String>,
{
transform_fn(content).map_err(ProcessError::ContentError)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_read_content() {
let result = read_content("test_file.txt");
assert!(
result.is_ok()
|| matches!(result, Err(ProcessError::InvalidPath(_)))
);
}
#[test]
fn test_write_content() {
let file_path = "test_output.txt";
let result = write_content(file_path, "Sample content");
assert!(
result.is_ok() || matches!(result, Err(ProcessError::WriteError(_)))
);
if Path::new(file_path).exists() {
std::fs::remove_file(file_path).expect("Failed to delete test output file");
}
}
#[test]
fn test_process_content() {
let transform_fn = |s: &str| Ok(s.to_uppercase());
let result = process_content("test content", transform_fn);
assert_eq!(result.unwrap(), "TEST CONTENT");
}
}