use std::collections::HashMap;
use std::{io, fs, path::Path};
use std::fmt::{Debug, self, Display};
#[derive(Debug)]
pub enum ReadError<T> {
Io(io::Error),
Parse(T),
}
impl<T> From<io::Error> for ReadError<T> {
fn from(err: io::Error) -> Self {
ReadError::Io(err)
}
}
impl<T: Display> Display for ReadError<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ReadError::Io(err) => write!(f, "IO error: {}", err),
ReadError::Parse(err) => write!(f, "Parse error: {}", err),
}
}
}
pub trait Readable: Sized {
type ParseError;
fn load<R: io::Read>(reader: &mut R) -> Result<Self, ReadError<Self::ParseError>>;
fn load_file<P: AsRef<Path>>(path: P) -> Result<Self, ReadError<Self::ParseError>> {
Self::load(&mut fs::File::open(path)?)
}
fn load_all<P: AsRef<Path>>(path: P) -> HashMap<String, Self> {
let mut map = HashMap::new();
if let Ok(entries) = fs::read_dir(path) {
for entry in entries {
if let Ok(entry) = entry {
if let Some(name) = entry.file_name().to_str() {
if let Ok(obj) = Self::load_file(entry.path()) {
map.insert(name.to_owned(), obj);
}
}
}
}
}
map
}
}