linked-data 0.1.2

Linked-Data dateset serialization/deserialization traits
Documentation
#[macro_export]
macro_rules! json_literal {
	($ty:ty) => {
		impl<V: $crate::rdf_types::Vocabulary, I: $crate::rdf_types::Interpretation> $crate::LinkedDataResource<I, V> for $ty {
			fn interpretation(
				&self,
				_vocabulary: &mut V,
				_interpretation: &mut I,
			) -> $crate::ResourceInterpretation<I, V> {
				use $crate::{rdf_types::Term, CowRdfTerm, RdfLiteral, ResourceInterpretation};

				let mut value = $crate::json_syntax::to_value(self).unwrap();
				value.canonicalize();

				ResourceInterpretation::Uninterpreted(Some(CowRdfTerm::Owned(Term::Literal(
					RdfLiteral::Json(value),
				))))
			}
		}

		impl<V: $crate::rdf_types::Vocabulary, I: $crate::rdf_types::Interpretation> $crate::LinkedDataPredicateObjects<I, V> for $ty {
			fn visit_objects<S>(&self, mut visitor: S) -> Result<S::Ok, S::Error>
			where
				S: $crate::PredicateObjectsVisitor<I, V>,
			{
				visitor.object(self)?;
				visitor.end()
			}
		}

		impl<V: $crate::rdf_types::Vocabulary, I: $crate::rdf_types::Interpretation> $crate::LinkedDataDeserializePredicateObjects<I, V> for $ty
		where
			V: $crate::rdf_types::Vocabulary,
			I: $crate::rdf_types::interpretation::ReverseIriInterpretation<Iri = V::Iri> + $crate::rdf_types::interpretation::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::Resource>,
				context: $crate::Context<I>
			) -> Result<Self, $crate::FromLinkedDataError>
			where
				I::Resource: 'a,
				D: $crate::rdf_types::dataset::PatternMatchingDataset<Resource = I::Resource>
			{
				let mut objects = objects.into_iter();
				match objects.next() {
					Some(object) => {
						if objects.next().is_none() {
							<Self as $crate::LinkedDataDeserializeSubject<I, V>>::deserialize_subject_in(vocabulary, interpretation, dataset, graph, object, context)
						} else {
							Err($crate::FromLinkedDataError::TooManyValues(
								context.into_iris(vocabulary, interpretation)
							))
						}
					}
					None => {
						Err($crate::FromLinkedDataError::MissingRequiredValue(
							context.into_iris(vocabulary, interpretation)
						))
					}
				}
			}
		}

		impl<V: $crate::rdf_types::Vocabulary, I: $crate::rdf_types::Interpretation> $crate::LinkedDataSubject<I, V> for $ty {
			fn visit_subject<S>(&self, visitor: S) -> Result<S::Ok, S::Error>
			where
				S: $crate::SubjectVisitor<I, V>,
			{
				visitor.end()
			}
		}

		impl<V: $crate::rdf_types::Vocabulary, I: $crate::rdf_types::Interpretation> $crate::LinkedDataDeserializeSubject<I, V> for $ty
		where
			V: $crate::rdf_types::Vocabulary,
			I: $crate::rdf_types::interpretation::ReverseIriInterpretation<Iri = V::Iri> + $crate::rdf_types::interpretation::ReverseLiteralInterpretation<Literal = V::Literal>
		{
			fn deserialize_subject_in<D>(
				vocabulary: &V,
				interpretation: &I,
				_dataset: &D,
				_graph: Option<&I::Resource>,
				resource: &I::Resource,
				context: $crate::Context<I>
			) -> Result<Self, $crate::FromLinkedDataError>
			where
				D: $crate::rdf_types::dataset::PatternMatchingDataset<Resource = I::Resource>
			{
				use $crate::rdf_types::LiteralTypeRef;

				let mut literal_ty = None;
				for l in interpretation.literals_of(resource) {
					let literal = vocabulary.literal(l).unwrap();
					match literal.type_ {
						LiteralTypeRef::Any(ty) => {
							let ty_iri = vocabulary.iri(ty).unwrap();
							if ty_iri == $crate::rdf_types::RDF_JSON {
								use $crate::json_syntax::Parse;
								let (json, _) = $crate::json_syntax::Value::parse_str(literal.value)
									.map_err(|_| $crate::FromLinkedDataError::InvalidLiteral(
										context.into_iris(vocabulary, interpretation)
									))?;

								return $crate::json_syntax::from_value(json).map_err(|_| $crate::FromLinkedDataError::InvalidLiteral(
									context.into_iris(vocabulary, interpretation)
								))
							} else {
								literal_ty = Some(ty_iri)
							}
						}
						LiteralTypeRef::LangString(_) => {
							literal_ty = Some($crate::rdf_types::RDF_LANG_STRING)
						}
					}
				}

				match literal_ty {
					Some(ty) => {
						Err($crate::FromLinkedDataError::LiteralTypeMismatch {
							context: context.into_iris(vocabulary, interpretation),
							expected: Some($crate::rdf_types::RDF_JSON.to_owned()),
							found: ty.to_owned()
						})
					}
					None => {
						Err($crate::FromLinkedDataError::ExpectedLiteral(
							context.into_iris(vocabulary, interpretation)
						))
					}
				}
			}
		}
	};
}

#[cfg(test)]
mod test {
	#[derive(Debug, serde::Serialize, serde::Deserialize)]
	struct Test {
		field: String,
	}

	json_literal!(Test);
}