use crate::{LoaderError, LoadingResult};
use iref::IriBuf;
use rdf_types::vocabulary::IriVocabularyMut;
use std::fmt;
use super::Loader;
pub struct ChainLoader<L1, L2>(L1, L2);
impl<L1, L2> ChainLoader<L1, L2> {
pub fn new(l1: L1, l2: L2) -> Self {
ChainLoader(l1, l2)
}
}
impl<I, L1, L2> Loader<I> for ChainLoader<L1, L2>
where
I: Clone,
L1: Loader<I>,
L2: Loader<I>,
{
type Error = Error<L1::Error, L2::Error>;
async fn load_with<V>(&mut self, vocabulary: &mut V, url: I) -> LoadingResult<I, Self::Error>
where
V: IriVocabularyMut<Iri = I>,
{
match self.0.load_with(vocabulary, url.clone()).await {
Ok(doc) => Ok(doc),
Err(err1) => match self.1.load_with(vocabulary, url).await {
Ok(doc) => Ok(doc),
Err(err2) => Err(Error(err1, err2)),
},
}
}
}
#[derive(Debug)]
pub struct Error<E1, E2>(E1, E2);
impl<E1: fmt::Display, E2: fmt::Display> fmt::Display for Error<E1, E2> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let Error(e1, e2) = self;
write!(f, "{e1}, then {e2}")
}
}
impl<E1: std::error::Error, E2: std::error::Error> std::error::Error for Error<E1, E2> {}
impl<E1: LoaderError, E2: LoaderError> LoaderError for Error<E1, E2> {
fn into_iri_and_message(self) -> (IriBuf, String) {
let (iri, m1) = self.0.into_iri_and_message();
let (_, m2) = self.1.into_iri_and_message();
(iri, format!("{m1}, then {m2}"))
}
}