use rdf_types::{
Interpretation, RDF_LANG_STRING, Vocabulary,
interpretation::{ReverseIriInterpretation, ReverseLiteralInterpretation},
vocabulary::LiteralVocabulary,
};
use crate::{
Context, FromLinkedDataError, LinkedDataDeserializePredicateObjects,
LinkedDataDeserializeSubject,
};
macro_rules! deserialize_datatype {
($ty:ty, $iri:ident, $($extra_type:expr)*) => {
impl<V: Vocabulary, I: Interpretation> LinkedDataDeserializeSubject<I, V> for $ty
where
V: LiteralVocabulary,
I: ReverseIriInterpretation<Iri = V::Iri> + ReverseLiteralInterpretation<Literal = V::Literal>
{
fn deserialize_subject_in<D>(
vocabulary: &V,
interpretation: &I,
_dataset: &D,
_graph: Option<&I::Resource>,
resource: &I::Resource,
context: Context<I>
) -> Result<Self, FromLinkedDataError>
where
D: rdf_types::dataset::PatternMatchingDataset<Resource = I::Resource>
{
let mut literal_ty = None;
for l in interpretation.literals_of(resource) {
let l = vocabulary.literal(l).unwrap();
match l.type_ {
rdf_types::LiteralTypeRef::Any(ty_iri) => {
let ty_iri = vocabulary.iri(ty_iri).unwrap();
if ty_iri == xsd_types::$iri $(|| ty_iri == $extra_type)* {
return match l.value.parse() {
Ok(value) => Ok(value),
Err(_) => Err(FromLinkedDataError::InvalidLiteral(
context.into_iris(
vocabulary,
interpretation
)
))
}
}
literal_ty = Some(ty_iri)
}
rdf_types::LiteralTypeRef::LangString(_) => {
literal_ty = Some(RDF_LANG_STRING)
}
}
}
match literal_ty {
Some(ty) => {
Err(FromLinkedDataError::LiteralTypeMismatch {
context: context.into_iris(vocabulary, interpretation),
expected: Some(xsd_types::$iri.to_owned()),
found: ty.to_owned()
})
}
None => {
Err(FromLinkedDataError::ExpectedLiteral(
context.into_iris(vocabulary, interpretation)
))
}
}
}
}
impl<V: Vocabulary, I: Interpretation> LinkedDataDeserializePredicateObjects<I, V> for $ty
where
V: LiteralVocabulary,
I: ReverseIriInterpretation<Iri = V::Iri> + ReverseLiteralInterpretation<Literal = V::Literal>
{
fn deserialize_objects_in<'a, D>(
vocabulary: &V,
interpretation: &I,
dataset: &D,
graph: Option<&I::Resource>,
objects: impl IntoIterator<Item = &'a <I as Interpretation>::Resource>,
context: Context<I>
) -> Result<Self, FromLinkedDataError>
where
<I as Interpretation>::Resource: 'a,
D: rdf_types::dataset::PatternMatchingDataset<Resource = I::Resource>
{
let mut error = None;
for o in objects {
match Self::deserialize_subject_in(vocabulary, interpretation, dataset, graph, o, context) {
Ok(value) => return Ok(value),
Err(e) => error = Some(e)
}
}
Err(error.unwrap_or_else(|| {
FromLinkedDataError::MissingRequiredValue(
context.into_iris(vocabulary, interpretation)
)
}))
}
}
};
}
deserialize_datatype!(bool, XSD_BOOLEAN,);
deserialize_datatype!(u8, XSD_UNSIGNED_BYTE, xsd_types::XSD_INTEGER);
deserialize_datatype!(u16, XSD_UNSIGNED_SHORT, xsd_types::XSD_INTEGER);
deserialize_datatype!(u32, XSD_UNSIGNED_INT, xsd_types::XSD_INTEGER);
deserialize_datatype!(u64, XSD_UNSIGNED_LONG, xsd_types::XSD_INTEGER);
deserialize_datatype!(i8, XSD_BYTE, xsd_types::XSD_INTEGER);
deserialize_datatype!(i16, XSD_SHORT, xsd_types::XSD_INTEGER);
deserialize_datatype!(i32, XSD_INT, xsd_types::XSD_INTEGER);
deserialize_datatype!(i64, XSD_LONG, xsd_types::XSD_INTEGER);
deserialize_datatype!(f32, XSD_FLOAT, xsd_types::XSD_DECIMAL);
deserialize_datatype!(f64, XSD_DOUBLE, xsd_types::XSD_DECIMAL);
deserialize_datatype!(String, XSD_STRING,);
deserialize_datatype!(xsd_types::DateTime, XSD_DATE_TIME,);