1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#[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);
}