linked_data/
macros.rs

1#[macro_export]
2macro_rules! json_literal {
3	($ty:ty) => {
4		impl<V: $crate::rdf_types::Vocabulary, I: $crate::rdf_types::Interpretation> $crate::LinkedDataResource<I, V> for $ty {
5			fn interpretation(
6				&self,
7				_vocabulary: &mut V,
8				_interpretation: &mut I,
9			) -> $crate::ResourceInterpretation<I, V> {
10				use $crate::{rdf_types::Term, CowRdfTerm, RdfLiteral, ResourceInterpretation};
11
12				let mut value = $crate::json_syntax::to_value(self).unwrap();
13				value.canonicalize();
14
15				ResourceInterpretation::Uninterpreted(Some(CowRdfTerm::Owned(Term::Literal(
16					RdfLiteral::Json(value),
17				))))
18			}
19		}
20
21		impl<V: $crate::rdf_types::Vocabulary, I: $crate::rdf_types::Interpretation> $crate::LinkedDataPredicateObjects<I, V> for $ty {
22			fn visit_objects<S>(&self, mut visitor: S) -> Result<S::Ok, S::Error>
23			where
24				S: $crate::PredicateObjectsVisitor<I, V>,
25			{
26				visitor.object(self)?;
27				visitor.end()
28			}
29		}
30
31		impl<V: $crate::rdf_types::Vocabulary, I: $crate::rdf_types::Interpretation> $crate::LinkedDataDeserializePredicateObjects<I, V> for $ty
32		where
33			V: $crate::rdf_types::Vocabulary,
34			I: $crate::rdf_types::interpretation::ReverseIriInterpretation<Iri = V::Iri> + $crate::rdf_types::interpretation::ReverseLiteralInterpretation<Literal = V::Literal>
35		{
36			fn deserialize_objects_in<'a, D>(
37				vocabulary: &V,
38				interpretation: &I,
39				dataset: &D,
40				graph: Option<&I::Resource>,
41				objects: impl IntoIterator<Item = &'a I::Resource>,
42				context: $crate::Context<I>
43			) -> Result<Self, $crate::FromLinkedDataError>
44			where
45				I::Resource: 'a,
46				D: $crate::rdf_types::dataset::PatternMatchingDataset<Resource = I::Resource>
47			{
48				let mut objects = objects.into_iter();
49				match objects.next() {
50					Some(object) => {
51						if objects.next().is_none() {
52							<Self as $crate::LinkedDataDeserializeSubject<I, V>>::deserialize_subject_in(vocabulary, interpretation, dataset, graph, object, context)
53						} else {
54							Err($crate::FromLinkedDataError::TooManyValues(
55								context.into_iris(vocabulary, interpretation)
56							))
57						}
58					}
59					None => {
60						Err($crate::FromLinkedDataError::MissingRequiredValue(
61							context.into_iris(vocabulary, interpretation)
62						))
63					}
64				}
65			}
66		}
67
68		impl<V: $crate::rdf_types::Vocabulary, I: $crate::rdf_types::Interpretation> $crate::LinkedDataSubject<I, V> for $ty {
69			fn visit_subject<S>(&self, visitor: S) -> Result<S::Ok, S::Error>
70			where
71				S: $crate::SubjectVisitor<I, V>,
72			{
73				visitor.end()
74			}
75		}
76
77		impl<V: $crate::rdf_types::Vocabulary, I: $crate::rdf_types::Interpretation> $crate::LinkedDataDeserializeSubject<I, V> for $ty
78		where
79			V: $crate::rdf_types::Vocabulary,
80			I: $crate::rdf_types::interpretation::ReverseIriInterpretation<Iri = V::Iri> + $crate::rdf_types::interpretation::ReverseLiteralInterpretation<Literal = V::Literal>
81		{
82			fn deserialize_subject_in<D>(
83				vocabulary: &V,
84				interpretation: &I,
85				_dataset: &D,
86				_graph: Option<&I::Resource>,
87				resource: &I::Resource,
88				context: $crate::Context<I>
89			) -> Result<Self, $crate::FromLinkedDataError>
90			where
91				D: $crate::rdf_types::dataset::PatternMatchingDataset<Resource = I::Resource>
92			{
93				use $crate::rdf_types::LiteralTypeRef;
94
95				let mut literal_ty = None;
96				for l in interpretation.literals_of(resource) {
97					let literal = vocabulary.literal(l).unwrap();
98					match literal.type_ {
99						LiteralTypeRef::Any(ty) => {
100							let ty_iri = vocabulary.iri(ty).unwrap();
101							if ty_iri == $crate::rdf_types::RDF_JSON {
102								use $crate::json_syntax::Parse;
103								let (json, _) = $crate::json_syntax::Value::parse_str(literal.value)
104									.map_err(|_| $crate::FromLinkedDataError::InvalidLiteral(
105										context.into_iris(vocabulary, interpretation)
106									))?;
107
108								return $crate::json_syntax::from_value(json).map_err(|_| $crate::FromLinkedDataError::InvalidLiteral(
109									context.into_iris(vocabulary, interpretation)
110								))
111							} else {
112								literal_ty = Some(ty_iri)
113							}
114						}
115						LiteralTypeRef::LangString(_) => {
116							literal_ty = Some($crate::rdf_types::RDF_LANG_STRING)
117						}
118					}
119				}
120
121				match literal_ty {
122					Some(ty) => {
123						Err($crate::FromLinkedDataError::LiteralTypeMismatch {
124							context: context.into_iris(vocabulary, interpretation),
125							expected: Some($crate::rdf_types::RDF_JSON.to_owned()),
126							found: ty.to_owned()
127						})
128					}
129					None => {
130						Err($crate::FromLinkedDataError::ExpectedLiteral(
131							context.into_iris(vocabulary, interpretation)
132						))
133					}
134				}
135			}
136		}
137	};
138}
139
140#[cfg(test)]
141mod test {
142	#[derive(Debug, serde::Serialize, serde::Deserialize)]
143	struct Test {
144		field: String,
145	}
146
147	json_literal!(Test);
148}