pub mod file_system_reader;
pub mod reader;
use std::fs;
use std::io;
use std::path::PathBuf;
use crate::error::{CliError, Result};
#[derive(Debug)]
pub struct ReaderFileLackPermissionsError(pub io::Error);
pub trait Reader {
fn read(&self, name: &str) -> Result<String>;
}
#[derive(Clone, Debug)]
pub struct FileSystemReader {
directory: PathBuf,
}
impl FileSystemReader {
pub fn new(directory: impl Into<PathBuf>) -> Self {
Self {
directory: directory.into(),
}
}
pub fn read_any_of(&self, filenames: &[&str]) -> Result<Option<String>> {
let mut first_permission_error = None;
for filename in filenames {
match self.read(filename) {
Ok(content) => return Ok(Some(content)),
Err(CliError::Io(error)) if error.kind() == io::ErrorKind::NotFound => {}
Err(CliError::Io(error)) if is_permission_error(&error) => {
first_permission_error.get_or_insert(error);
}
Err(error) => return Err(error),
}
}
if let Some(error) = first_permission_error {
Err(CliError::Io(error))
} else {
Ok(None)
}
}
pub fn directory(&self) -> &std::path::Path {
&self.directory
}
}
impl Reader for FileSystemReader {
fn read(&self, name: &str) -> Result<String> {
fs::read_to_string(self.directory.join(name)).map_err(CliError::from)
}
}
fn is_permission_error(error: &io::Error) -> bool {
matches!(
error.kind(),
io::ErrorKind::PermissionDenied | io::ErrorKind::ReadOnlyFilesystem
)
}