use crate::{
ByteBuffer, Error, Language, ReadableFile,
excel::Sheet,
exh::EXH,
resource::{
generic_get_all_sheet_names, generic_parsed, generic_read_excel_sheet,
generic_read_excel_sheet_header,
},
};
use super::Resource;
#[derive(Clone)]
pub struct ResourceResolver {
resources: Vec<Box<dyn Resource>>,
}
impl ResourceResolver {
pub fn new() -> Self {
Self {
resources: Vec::new(),
}
}
pub fn add_source(&mut self, source: impl Resource) {
self.resources.push(Box::new(source));
}
pub fn read(&mut self, path: &str) -> Option<ByteBuffer> {
for resolver in &mut self.resources {
if let Some(bytes) = resolver.read(path) {
return Some(bytes);
}
}
None
}
pub fn parsed<F: ReadableFile>(&mut self, path: &str) -> Result<F, Error> {
self.execute_first_found(
|resource| generic_parsed(resource, path),
Error::FileNotFound {
path: path.to_string(),
},
)
}
pub fn read_excel_sheet_header(&mut self, name: &str) -> Result<EXH, Error> {
self.execute_first_found(
|resource| generic_read_excel_sheet_header(resource, name),
Error::Unknown,
)
}
pub fn read_excel_sheet(
&mut self,
exh: &EXH,
name: &str,
language: Language,
) -> Result<Sheet, Error> {
self.execute_first_found(
|resource| generic_read_excel_sheet(resource, exh, name, language),
Error::Unknown,
)
}
pub fn get_all_sheet_names(&mut self) -> Result<Vec<String>, Error> {
self.execute_first_found(generic_get_all_sheet_names, Error::Unknown)
}
pub fn exists(&mut self, path: &str) -> bool {
for resolver in &mut self.resources {
if resolver.exists(path) {
return true;
}
}
false
}
fn execute_first_found<T, F>(&mut self, f: F, error: Error) -> Result<T, Error>
where
F: Fn(&mut dyn Resource) -> Result<T, Error>,
{
for resource in &mut self.resources {
let result = f(resource.as_mut());
match result {
Ok(t) => return Ok(t),
Err(err) => {
if let Error::FileNotFound { .. } = err {
continue; } else {
return Err(err);
}
}
}
}
Err(error)
}
}