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