1use educe::Educe;
45use iref::{Iri, IriBuf};
46#[cfg(feature = "derive")]
47pub use linked_data_next_derive::{Deserialize, Serialize};
48use rdf_types::{
49 Interpretation, Vocabulary,
50 dataset::{PatternMatchingDataset, TraversableDataset},
51 interpretation::ReverseIriInterpretation,
52 vocabulary::IriVocabulary,
53};
54
55#[doc(hidden)]
56pub use iref;
57
58#[doc(hidden)]
59pub use rdf_types;
60
61#[doc(hidden)]
62pub use xsd_types;
63
64#[doc(hidden)]
65pub use json_syntax;
66
67mod anonymous;
68mod datatypes;
69mod graph;
70mod r#impl;
71mod macros;
72mod predicate;
73mod quads;
74mod rdf;
75mod rdf_list;
76mod reference;
77mod resource;
78mod subject;
79
80pub use anonymous::*;
81pub use graph::*;
82pub use predicate::*;
83pub use quads::{
84 IntoQuadsError, to_interpreted_graph_quads, to_interpreted_quads, to_interpreted_subject_quads,
85 to_lexical_quads, to_lexical_quads_with, to_lexical_subject_quads,
86 to_lexical_subject_quads_with, to_quads, to_quads_with,
87};
88pub use rdf::*;
89pub use reference::*;
90pub use resource::*;
91pub use subject::*;
92
93#[derive(Debug, thiserror::Error)]
94pub enum FromLinkedDataError {
95 #[error("expected IRI")]
97 ExpectedIri(ContextIris),
98
99 #[error("unsupported IRI `{found}`")]
100 UnsupportedIri {
101 context: ContextIris,
103
104 found: IriBuf,
106
107 supported: Option<Vec<IriBuf>>,
109 },
110
111 #[error("expected literal")]
113 ExpectedLiteral(ContextIris),
114
115 #[error("literal type mismatch")]
117 LiteralTypeMismatch {
118 context: ContextIris,
119 expected: Option<IriBuf>,
120 found: IriBuf,
121 },
122
123 #[error("invalid literal")]
126 InvalidLiteral(ContextIris),
127
128 #[error("missing required value")]
130 MissingRequiredValue(ContextIris),
131
132 #[error("too many values")]
134 TooManyValues(ContextIris),
135
136 #[error("invalid subject")]
138 InvalidSubject {
139 context: ContextIris,
140 subject: Option<IriBuf>,
141 },
142}
143
144impl FromLinkedDataError {
145 pub fn context(&self) -> &ContextIris {
146 match self {
147 Self::ExpectedIri(c) => c,
148 Self::UnsupportedIri { context, .. } => context,
149 Self::ExpectedLiteral(c) => c,
150 Self::LiteralTypeMismatch { context, .. } => context,
151 Self::InvalidLiteral(c) => c,
152 Self::MissingRequiredValue(c) => c,
153 Self::TooManyValues(c) => c,
154 Self::InvalidSubject { context, .. } => context,
155 }
156 }
157}
158
159pub trait LinkedData<I: Interpretation = (), V: Vocabulary = ()> {
164 fn visit<S>(&self, visitor: S) -> Result<S::Ok, S::Error>
166 where
167 S: Visitor<I, V>;
168}
169
170impl<I: Interpretation, V: Vocabulary, T: ?Sized + LinkedData<I, V>> LinkedData<I, V> for &T {
171 fn visit<S>(&self, visitor: S) -> Result<S::Ok, S::Error>
172 where
173 S: Visitor<I, V>,
174 {
175 T::visit(self, visitor)
176 }
177}
178
179impl<I: Interpretation, V: Vocabulary, T: ?Sized + LinkedData<I, V>> LinkedData<I, V> for Box<T> {
180 fn visit<S>(&self, visitor: S) -> Result<S::Ok, S::Error>
181 where
182 S: Visitor<I, V>,
183 {
184 T::visit(self, visitor)
185 }
186}
187
188impl<I: Interpretation, V: Vocabulary> LinkedData<I, V> for Iri {
189 fn visit<S>(&self, visitor: S) -> Result<S::Ok, S::Error>
190 where
191 S: Visitor<I, V>,
192 {
193 visitor.end()
194 }
195}
196
197pub trait Visitor<I: Interpretation = (), V: Vocabulary = ()> {
199 type Ok;
202
203 type Error;
205
206 fn default_graph<T>(&mut self, value: &T) -> Result<(), Self::Error>
208 where
209 T: ?Sized + LinkedDataGraph<I, V>;
210
211 fn named_graph<T>(&mut self, value: &T) -> Result<(), Self::Error>
213 where
214 T: ?Sized + LinkedDataResource<I, V> + LinkedDataGraph<I, V>;
215
216 fn end(self) -> Result<Self::Ok, Self::Error>;
218}
219
220impl<I: Interpretation, V: Vocabulary, S: Visitor<I, V>> Visitor<I, V> for &mut S {
222 type Ok = ();
223 type Error = S::Error;
224
225 fn default_graph<T>(&mut self, value: &T) -> Result<(), Self::Error>
226 where
227 T: ?Sized + LinkedDataGraph<I, V>,
228 {
229 S::default_graph(self, value)
230 }
231
232 fn named_graph<T>(&mut self, value: &T) -> Result<(), Self::Error>
233 where
234 T: ?Sized + LinkedDataResource<I, V> + LinkedDataGraph<I, V>,
235 {
236 S::named_graph(self, value)
237 }
238
239 fn end(self) -> Result<Self::Ok, Self::Error> {
240 Ok(())
241 }
242}
243
244#[derive(Educe)]
245#[educe(Debug(bound = "I::Resource: core::fmt::Debug"), Clone, Copy)]
246pub enum ResourceOrIriRef<'a, I: Interpretation> {
247 Resource(&'a I::Resource),
248 Iri(&'a Iri),
249 Anonymous,
250}
251
252impl<I: Interpretation> ResourceOrIriRef<'_, I> {
253 pub fn into_iri<V>(self, vocabulary: &V, interpretation: &I) -> Option<IriBuf>
254 where
255 V: IriVocabulary,
256 I: ReverseIriInterpretation<Iri = V::Iri>,
257 {
258 match self {
259 Self::Resource(r) => interpretation
260 .iris_of(r)
261 .next()
262 .map(|i| vocabulary.iri(i).unwrap().to_owned()),
263 Self::Iri(i) => Some(i.to_owned()),
264 Self::Anonymous => None,
265 }
266 }
267}
268
269#[derive(Default, Educe)]
270#[educe(Debug(bound = "I::Resource: core::fmt::Debug"), Clone, Copy)]
271pub enum Context<'a, I: Interpretation> {
272 #[default]
273 Subject,
274 Predicate {
275 subject: ResourceOrIriRef<'a, I>,
276 },
277 Object {
278 subject: ResourceOrIriRef<'a, I>,
279 predicate: ResourceOrIriRef<'a, I>,
280 },
281}
282
283impl<'a, I: Interpretation> Context<'a, I> {
284 pub fn with_subject(self, subject: &'a I::Resource) -> Self {
285 Self::Predicate {
286 subject: ResourceOrIriRef::Resource(subject),
287 }
288 }
289
290 pub fn with_predicate(self, predicate: &'a I::Resource) -> Self {
291 match self {
292 Self::Predicate { subject } => Self::Object {
293 subject,
294 predicate: ResourceOrIriRef::Resource(predicate),
295 },
296 _ => Self::Subject,
297 }
298 }
299
300 pub fn with_predicate_iri(self, predicate: &'a Iri) -> Self {
301 match self {
302 Self::Predicate { subject } => Self::Object {
303 subject,
304 predicate: ResourceOrIriRef::Iri(predicate),
305 },
306 _ => Self::Subject,
307 }
308 }
309
310 pub fn with_anonymous_predicate(self) -> Self {
311 match self {
312 Self::Predicate { subject } => Self::Object {
313 subject,
314 predicate: ResourceOrIriRef::Anonymous,
315 },
316 _ => Self::Subject,
317 }
318 }
319
320 pub fn into_iris<V>(self, vocabulary: &V, interpretation: &I) -> ContextIris
321 where
322 V: IriVocabulary,
323 I: ReverseIriInterpretation<Iri = V::Iri>,
324 {
325 match self {
326 Self::Subject => ContextIris::Subject,
327 Self::Predicate { subject } => ContextIris::Predicate {
328 subject: subject.into_iri(vocabulary, interpretation),
329 },
330 Self::Object { subject, predicate } => ContextIris::Object {
331 subject: subject.into_iri(vocabulary, interpretation),
332 predicate: predicate.into_iri(vocabulary, interpretation),
333 },
334 }
335 }
336}
337
338#[derive(Debug, Clone)]
339pub enum ContextIris {
340 Subject,
341 Predicate {
342 subject: Option<IriBuf>,
343 },
344 Object {
345 subject: Option<IriBuf>,
346 predicate: Option<IriBuf>,
347 },
348}
349
350pub trait LinkedDataDeserialize<V: Vocabulary = (), I: Interpretation = ()>: Sized {
351 fn deserialize_dataset_in(
352 vocabulary: &V,
353 interpretation: &I,
354 dataset: &(impl TraversableDataset<Resource = I::Resource> + PatternMatchingDataset),
355 context: Context<I>,
356 ) -> Result<Self, FromLinkedDataError>;
357
358 fn deserialize_dataset(
359 vocabulary: &V,
360 interpretation: &I,
361 dataset: &(impl TraversableDataset<Resource = I::Resource> + PatternMatchingDataset),
362 ) -> Result<Self, FromLinkedDataError> {
363 Self::deserialize_dataset_in(vocabulary, interpretation, dataset, Context::default())
364 }
365}