linked-data-next 0.2.0

Linked-Data dateset serialization/deserialization traits
Documentation
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,);