use std::borrow::Borrow;
use smallvec::SmallVec;
use sophia_api::{
MownStr,
source::TripleSource,
term::{IriRef, SimpleTerm},
triple::Triple,
};
mod _nothing;
pub use _nothing::Nothing;
mod _and;
pub use _and::And;
mod _sparql;
pub use _sparql::Sparql;
mod _triple_source;
pub use _triple_source::{NormalizeError, NormalizeTriples};
pub trait Recognized: Send + Sync {
fn try_normalize<T: Borrow<str>>(
lex_dt: LexDt<T>,
) -> Result<Result<LexDt<Box<str>>, IllTypedLiteral>, LexDt<T>>;
fn datatypes() -> impl Iterator<Item = IriRef<MownStr<'static>>> + Send;
fn witnesses() -> impl Iterator<Item = (MownStr<'static>, IriRef<MownStr<'static>>)> + Send;
fn datatypes_for(
lex: &str,
datatype: IriRef<&str>,
) -> Option<SmallVec<[IriRef<MownStr<'static>>; 16]>>;
fn normalize_or_fallback<T: Borrow<str> + From<Box<str>>>(
lex_dt: LexDt<T>,
) -> Result<LexDt<T>, IllTypedLiteral> {
Self::try_normalize(lex_dt)
.map(|res| res.map(|(lex, dt)| (lex.into(), dt)))
.unwrap_or_else(Ok)
}
fn normalize_simple_term(t: SimpleTerm<'_>) -> Result<SimpleTerm<'_>, IllTypedLiteral> {
Ok(match t {
SimpleTerm::LiteralDatatype(lex, dt) => {
let (lex, dt) = Self::normalize_or_fallback((lex, dt))?;
SimpleTerm::LiteralDatatype(lex, dt)
}
SimpleTerm::Triple(tr) => {
let [s, p, o] = tr.to_spo();
let tr = [
Self::normalize_simple_term(s)?,
Self::normalize_simple_term(p)?,
Self::normalize_simple_term(o)?,
];
SimpleTerm::Triple(Box::new(tr))
}
_ => t,
})
}
fn normalize_triples<TS: TripleSource>(ts: TS) -> NormalizeTriples<Self, TS> {
NormalizeTriples::new(ts)
}
}
#[derive(Clone, Debug, thiserror::Error)]
#[error("Ill-typed literal {lex:?}^^<{datatype}>")]
pub struct IllTypedLiteral {
lex: Box<str>,
datatype: IriRef<Box<str>>,
}
impl IllTypedLiteral {
pub fn new<T: Borrow<str>>(lex: T, datatype: IriRef<T>) -> Self {
Self {
lex: Box::from(lex.borrow()),
datatype: datatype.as_ref().map_unchecked(Box::from),
}
}
}
pub type LexDt<'a, T> = (T, IriRef<MownStr<'a>>);