1use derive_more::Debug;
51use derive_where::derive_where;
52use iri_rs::{Iri, IriBuf};
53#[cfg(feature = "derive")]
54pub use ld_core_derive::{Deserialize, Serialize};
55use rdfx::{
56 Interpretation, dataset::PatternMatchingDataset, interpretation::ReverseInterpretation,
57};
58
59#[doc(hidden)]
60pub use iri_rs;
61
62#[doc(hidden)]
63pub use rdfx;
64
65#[doc(hidden)]
66pub use xsd_rs;
67
68#[doc(hidden)]
69pub use jstrict;
70
71mod anonymous;
72mod datatypes;
73mod graph;
74mod r#impl;
75mod macros;
76mod predicate;
77mod quads;
78mod rdf;
79mod reference;
80mod resource;
81mod subject;
82
83pub use anonymous::*;
84pub use graph::*;
85pub use predicate::*;
86pub use quads::{
87 IntoQuadsError, to_interpreted_graph_quads, to_interpreted_quads, to_interpreted_subject_quads,
88 to_lexical_quads, to_lexical_quads_with, to_lexical_subject_quads,
89 to_lexical_subject_quads_with, to_quads, to_quads_with,
90};
91pub use rdf::*;
92pub use reference::*;
93pub use resource::*;
94pub use subject::*;
95
96#[derive(Debug, thiserror::Error)]
97pub enum FromLinkedDataError {
99 #[error("expected IRI")]
101 ExpectedIri(ContextIris),
102
103 #[error("unsupported IRI `{found}`")]
104 UnsupportedIri {
106 context: ContextIris,
108
109 found: IriBuf,
111
112 supported: Option<Vec<IriBuf>>,
114 },
115
116 #[error("expected literal")]
118 ExpectedLiteral(ContextIris),
119
120 #[error("literal type mismatch")]
126 LiteralTypeMismatch {
127 context: ContextIris,
129 expected: Option<Box<IriBuf>>,
131 found: Box<IriBuf>,
133 },
134
135 #[error("invalid literal")]
138 InvalidLiteral(ContextIris),
139
140 #[error("missing required value")]
142 MissingRequiredValue(ContextIris),
143
144 #[error("too many values")]
146 TooManyValues(ContextIris),
147
148 #[error("invalid subject")]
150 InvalidSubject {
151 context: ContextIris,
153 subject: Option<IriBuf>,
155 },
156}
157
158impl FromLinkedDataError {
159 pub fn context(&self) -> &ContextIris {
161 match self {
162 Self::ExpectedIri(c) => c,
163 Self::UnsupportedIri { context, .. } => context,
164 Self::ExpectedLiteral(c) => c,
165 Self::LiteralTypeMismatch { context, .. } => context,
166 Self::InvalidLiteral(c) => c,
167 Self::MissingRequiredValue(c) => c,
168 Self::TooManyValues(c) => c,
169 Self::InvalidSubject { context, .. } => context,
170 }
171 }
172}
173
174pub trait LinkedData<I: Interpretation = ()> {
179 fn visit<S>(&self, visitor: S) -> Result<S::Ok, S::Error>
181 where
182 S: Visitor<I>;
183}
184
185impl<I: Interpretation, T: ?Sized + LinkedData<I>> LinkedData<I> for &T {
186 fn visit<S>(&self, visitor: S) -> Result<S::Ok, S::Error>
187 where
188 S: Visitor<I>,
189 {
190 T::visit(self, visitor)
191 }
192}
193
194impl<I: Interpretation, T: ?Sized + LinkedData<I>> LinkedData<I> for Box<T> {
195 fn visit<S>(&self, visitor: S) -> Result<S::Ok, S::Error>
196 where
197 S: Visitor<I>,
198 {
199 T::visit(self, visitor)
200 }
201}
202
203impl<I: Interpretation> LinkedData<I> for IriBuf {
204 fn visit<S>(&self, visitor: S) -> Result<S::Ok, S::Error>
205 where
206 S: Visitor<I>,
207 {
208 visitor.end()
209 }
210}
211
212pub trait Visitor<I: Interpretation = ()> {
214 type Ok;
217
218 type Error;
220
221 fn default_graph<T>(&mut self, value: &T) -> Result<(), Self::Error>
223 where
224 T: ?Sized + LinkedDataGraph<I>;
225
226 fn named_graph<T>(&mut self, value: &T) -> Result<(), Self::Error>
228 where
229 T: ?Sized + LinkedDataResource<I> + LinkedDataGraph<I>;
230
231 fn end(self) -> Result<Self::Ok, Self::Error>;
233}
234
235impl<I: Interpretation, S: Visitor<I>> Visitor<I> for &mut S {
237 type Ok = ();
238 type Error = S::Error;
239
240 fn default_graph<T>(&mut self, value: &T) -> Result<(), Self::Error>
241 where
242 T: ?Sized + LinkedDataGraph<I>,
243 {
244 S::default_graph(self, value)
245 }
246
247 fn named_graph<T>(&mut self, value: &T) -> Result<(), Self::Error>
248 where
249 T: ?Sized + LinkedDataResource<I> + LinkedDataGraph<I>,
250 {
251 S::named_graph(self, value)
252 }
253
254 fn end(self) -> Result<Self::Ok, Self::Error> {
255 Ok(())
256 }
257}
258
259#[derive(Debug)]
260#[debug(bound(I::Resource: core::fmt::Debug))]
261#[derive_where(Clone, Copy)]
262pub enum ResourceOrIriRef<'a, I: Interpretation> {
264 Resource(&'a I::Resource),
266 Iri(Iri<&'a str>),
268 Anonymous,
270}
271
272impl<'a, I: Interpretation> ResourceOrIriRef<'a, I> {
273 pub fn into_iri(self, interpretation: &I) -> Option<IriBuf>
275 where
276 I: ReverseInterpretation,
277 {
278 match self {
279 Self::Resource(r) => interpretation.iris_of(r).next().map(|i| i.into_owned()),
280 Self::Iri(i) => Some(i.into()),
281 Self::Anonymous => None,
282 }
283 }
284}
285
286#[derive(Debug)]
287#[debug(bound(I::Resource: core::fmt::Debug))]
288#[derive_where(Clone, Copy)]
289#[derive(Default)]
291pub enum Context<'a, I: Interpretation> {
292 #[default]
294 Subject,
295 Predicate {
297 subject: ResourceOrIriRef<'a, I>,
299 },
300 Object {
302 subject: ResourceOrIriRef<'a, I>,
304 predicate: ResourceOrIriRef<'a, I>,
306 },
307}
308
309impl<'a, I: Interpretation> Context<'a, I> {
310 pub fn with_subject(self, subject: &'a I::Resource) -> Self {
312 Self::Predicate {
313 subject: ResourceOrIriRef::Resource(subject),
314 }
315 }
316
317 pub fn with_predicate(self, predicate: &'a I::Resource) -> Self {
319 match self {
320 Self::Predicate { subject } => Self::Object {
321 subject,
322 predicate: ResourceOrIriRef::Resource(predicate),
323 },
324 _ => Self::Subject,
325 }
326 }
327
328 pub fn with_predicate_iri(self, predicate: Iri<&'a str>) -> Self {
330 match self {
331 Self::Predicate { subject } => Self::Object {
332 subject,
333 predicate: ResourceOrIriRef::Iri(predicate),
334 },
335 _ => Self::Subject,
336 }
337 }
338
339 pub fn with_anonymous_predicate(self) -> Self {
341 match self {
342 Self::Predicate { subject } => Self::Object {
343 subject,
344 predicate: ResourceOrIriRef::Anonymous,
345 },
346 _ => Self::Subject,
347 }
348 }
349
350 pub fn into_iris(self, interpretation: &I) -> ContextIris
352 where
353 I: ReverseInterpretation,
354 {
355 match self {
356 Self::Subject => ContextIris::Subject,
357 Self::Predicate { subject } => ContextIris::Predicate {
358 subject: subject.into_iri(interpretation).map(Box::new),
359 },
360 Self::Object { subject, predicate } => ContextIris::Object {
361 subject: subject.into_iri(interpretation).map(Box::new),
362 predicate: predicate.into_iri(interpretation).map(Box::new),
363 },
364 }
365 }
366}
367
368#[derive(Debug, Clone)]
369pub enum ContextIris {
377 Subject,
379 Predicate {
381 subject: Option<Box<IriBuf>>,
383 },
384 Object {
386 subject: Option<Box<IriBuf>>,
388 predicate: Option<Box<IriBuf>>,
390 },
391}
392
393pub trait LinkedDataDeserialize<I: Interpretation>: Sized
395where
396 I::Resource: rdfx::Resource,
397{
398 fn deserialize_dataset_in(
401 interpretation: &I,
402 dataset: &(
403 impl rdfx::dataset::TraversableDataset<Subject = I::Resource>
404 + PatternMatchingDataset<Subject = I::Resource>
405 ),
406 context: Context<I>,
407 ) -> Result<Self, FromLinkedDataError>;
408
409 fn deserialize_dataset(
411 interpretation: &I,
412 dataset: &(
413 impl rdfx::dataset::TraversableDataset<Subject = I::Resource>
414 + PatternMatchingDataset<Subject = I::Resource>
415 ),
416 ) -> Result<Self, FromLinkedDataError> {
417 Self::deserialize_dataset_in(interpretation, dataset, Context::default())
418 }
419}