1use std::fmt::{Debug, Display};
2
3use rdf_syntax::{
4 CowGroundTerm, CowTerm, Iri, IriBuf, Quad, RDF_FIRST, RDF_NIL, RDF_REST, Term,
5 pattern::LinearQuadPattern,
6};
7
8mod dataset;
9mod flatten;
10mod quads;
11mod replay;
12mod resources;
13
14pub use dataset::*;
15pub use flatten::*;
16pub use quads::*;
17pub use replay::*;
18pub use resources::*;
19
20pub trait DeserializeLinkedDataWith<Q, R: Clone + Ord = Term>: Sized {
21 fn deserialize_rdf_with<D>(
22 state: Q,
23 deserializer: D,
24 graph: Option<&R>,
25 ) -> Result<Self, D::Error>
26 where
27 D: LinkedDataDeserializer<R>;
28
29 fn deserialize_rdf_objects_with<D>(
30 state: Q,
31 mut deserializer: D,
32 subject: &R,
33 predicate: &R,
34 graph: Option<&R>,
35 ) -> Result<Self, D::Error>
36 where
37 D: LinkedDataDeserializer<R>,
38 {
39 let mut objects = Vec::new();
40
41 while let Some(quad) = deserializer.deserialize_quad(Quad(
42 Some(subject),
43 Some(predicate),
44 None,
45 Some(graph),
46 ))? {
47 objects.push(quad.into_object())
48 }
49
50 Self::deserialize_rdf_with(
51 state,
52 ResourcesDeserializer::new(deserializer, objects),
53 graph,
54 )
55 }
56}
57
58pub trait DeserializeLinkedData<R: Clone + Ord = Term>: Sized {
59 fn deserialize_rdf<D>(deserializer: D, graph: Option<&R>) -> Result<Self, D::Error>
60 where
61 D: LinkedDataDeserializer<R>;
62
63 fn deserialize_rdf_objects<D>(
64 mut deserializer: D,
65 subject: &R,
66 predicate: &R,
67 graph: Option<&R>,
68 ) -> Result<Self, D::Error>
69 where
70 D: LinkedDataDeserializer<R>,
71 {
72 let mut objects = Vec::new();
73
74 while let Some(quad) = deserializer.deserialize_quad(Quad(
75 Some(subject),
76 Some(predicate),
77 None,
78 Some(graph),
79 ))? {
80 objects.push(quad.into_object())
81 }
82
83 Self::deserialize_rdf(ResourcesDeserializer::new(deserializer, objects), graph)
84 }
85}
86
87impl<Q, R: Clone + Ord, T: DeserializeLinkedDataWith<Q, R>> DeserializeLinkedDataWith<Q, R>
88 for Option<T>
89{
90 fn deserialize_rdf_with<D>(
91 state: Q,
92 deserializer: D,
93 graph: Option<&R>,
94 ) -> Result<Self, D::Error>
95 where
96 D: LinkedDataDeserializer<R>,
97 {
98 if deserializer.peek_resources()?.next().transpose()?.is_some() {
99 T::deserialize_rdf_with(state, deserializer, graph).map(Some)
100 } else {
101 Ok(None)
102 }
103 }
104}
105
106impl<R: Clone + Ord, T: DeserializeLinkedData<R>> DeserializeLinkedData<R> for Option<T> {
107 fn deserialize_rdf<D>(deserializer: D, graph: Option<&R>) -> Result<Self, D::Error>
108 where
109 D: LinkedDataDeserializer<R>,
110 {
111 if deserializer.peek_resources()?.next().transpose()?.is_some() {
112 T::deserialize_rdf(deserializer, graph).map(Some)
113 } else {
114 Ok(None)
115 }
116 }
117}
118
119impl<R: Clone + Ord> DeserializeLinkedData<R> for Term {
120 fn deserialize_rdf<D>(mut deserializer: D, _graph: Option<&R>) -> Result<Self, D::Error>
121 where
122 D: LinkedDataDeserializer<R>,
123 {
124 let this = deserializer
125 .deserialize_resource(None)?
126 .ok_or_else(|| Error::missing_resource())?;
127
128 if let Some(term) = deserializer.terms_of(&this)?.next() {
129 return Ok(term?.into_owned());
130 }
131
132 Err(Error::custom("no IRI representation"))
133 }
134}
135
136impl<R: Clone + Ord> DeserializeLinkedData<R> for IriBuf {
137 fn deserialize_rdf<D>(mut deserializer: D, _graph: Option<&R>) -> Result<Self, D::Error>
138 where
139 D: LinkedDataDeserializer<R>,
140 {
141 let this = deserializer
142 .deserialize_resource(None)?
143 .ok_or_else(|| Error::missing_resource())?;
144
145 for term in deserializer.terms_of(&this)? {
146 if let CowTerm::Ground(CowGroundTerm::Iri(iri)) = term? {
147 return Ok(iri.into_owned());
148 }
149 }
150
151 Err(Error::custom("no IRI representation"))
152 }
153}
154
155impl<Q, T, R: Clone + Ord> DeserializeLinkedDataWith<Q, R> for Vec<T>
156where
157 Q: Clone,
158 T: DeserializeLinkedDataWith<Q, R>,
159{
160 fn deserialize_rdf_with<D>(
161 state: Q,
162 mut deserializer: D,
163 graph: Option<&R>,
164 ) -> Result<Self, D::Error>
165 where
166 D: LinkedDataDeserializer<R>,
167 {
168 let mut result = Vec::new();
169
170 let mut head = deserializer
171 .deserialize_resource(None)?
172 .ok_or_else(Error::missing_resource)?;
173
174 let prop_first = deserializer.interpret(RDF_FIRST.into())?;
175 let prop_rest = deserializer.interpret(RDF_REST.into())?;
176
177 'list: loop {
178 for term in deserializer.terms_of(&head)? {
179 if term? == RDF_NIL {
180 break 'list;
181 }
182 }
183
184 result.push(T::deserialize_rdf_objects_with(
185 state.clone(),
186 deserializer.as_dyn_mut(),
187 &head,
188 &prop_first,
189 graph,
190 )?);
191
192 head = deserializer
193 .deserialize_quad(Quad(Some(&head), Some(&prop_rest), None, Some(graph)))?
194 .ok_or_else(Error::missing_quad)?
195 .into_object();
196 }
197
198 Ok(result)
199 }
200}
201
202impl<T, R: Clone + Ord> DeserializeLinkedData<R> for Vec<T>
203where
204 T: DeserializeLinkedData<R>,
205{
206 fn deserialize_rdf<D>(mut deserializer: D, graph: Option<&R>) -> Result<Self, D::Error>
207 where
208 D: LinkedDataDeserializer<R>,
209 {
210 let mut result = Vec::new();
211
212 let mut head = deserializer
213 .deserialize_resource(None)?
214 .ok_or_else(Error::missing_resource)?;
215
216 let prop_first = deserializer.interpret(RDF_FIRST.into())?;
217 let prop_rest = deserializer.interpret(RDF_REST.into())?;
218
219 'list: loop {
220 for term in deserializer.terms_of(&head)? {
221 if term? == RDF_NIL {
222 break 'list;
223 }
224 }
225
226 result.push(T::deserialize_rdf_objects(
227 deserializer.as_dyn_mut(),
228 &head,
229 &prop_first,
230 graph,
231 )?);
232
233 head = deserializer
234 .deserialize_quad(Quad(Some(&head), Some(&prop_rest), None, Some(graph)))?
235 .ok_or_else(Error::missing_quad)?
236 .into_object();
237 }
238
239 Ok(result)
240 }
241}
242
243pub trait LinkedDataDeserializer<R = Term> {
244 type Error: Error<R>;
245
246 fn as_dyn_mut<'a>(
247 &'a mut self,
248 ) -> &'a mut (dyn 'a + DynLinkedDataDeserializer<R, Error = Self::Error>)
249 where
250 Self: Sized,
251 {
252 self
253 }
254
255 fn interpret(&mut self, term: CowTerm) -> Result<R, Self::Error>;
256
257 fn terms_of<'a>(
258 &'a self,
259 resource: &'a R,
260 ) -> Result<impl Iterator<Item = Result<CowTerm<'a>, Self::Error>>, Self::Error>;
261
262 fn is_iri(&self, resource: &R, iri: &Iri) -> Result<bool, Self::Error> {
263 for term in self.terms_of(resource)? {
264 if term? == iri {
265 return Ok(true);
266 }
267 }
268
269 Ok(false)
270 }
271
272 fn peek_resources<'a>(
273 &'a self,
274 ) -> Result<impl Iterator<Item = Result<&'a R, Self::Error>>, Self::Error>
275 where
276 R: 'a;
277
278 fn peek_resource<'a>(&'a self) -> Result<Option<&'a R>, Self::Error>
279 where
280 R: 'a,
281 {
282 self.peek_resources()?.next().transpose()
283 }
284
285 fn deserialize_resource(&mut self, resource: Option<R>) -> Result<Option<R>, Self::Error>;
286
287 fn peek_quads<'p>(
288 &'p self,
289 pattern: impl Into<LinearQuadPattern<&'p R>>,
290 ) -> Result<impl Iterator<Item = Result<Quad<&'p R>, Self::Error>>, Self::Error>
291 where
292 R: 'p;
293
294 fn peek_quad<'p>(
295 &'p self,
296 pattern: impl Into<LinearQuadPattern<&'p R>>,
297 ) -> Result<Option<Quad<&'p R>>, Self::Error>
298 where
299 R: 'p,
300 {
301 self.peek_quads(pattern)?.next().transpose()
302 }
303
304 fn deserialize_quad<'p>(
305 &mut self,
306 pattern: impl Into<LinearQuadPattern<&'p R>>,
307 ) -> Result<Option<Quad<R>>, Self::Error>
308 where
309 R: 'p;
310}
311
312pub trait DynLinkedDataDeserializer<R = Term> {
314 type Error: Error<R>;
315
316 fn interpret(&mut self, term: CowTerm) -> Result<R, Self::Error>;
317
318 fn terms_of<'a>(
319 &'a self,
320 resource: &'a R,
321 ) -> Result<DynTermIterator<'a, Self::Error>, Self::Error>;
322
323 fn peek_resources<'a>(&'a self) -> Result<DynResourceIterator<'a, R, Self::Error>, Self::Error>
324 where
325 R: 'a;
326
327 fn deserialize_resource(&mut self, resource: Option<R>) -> Result<Option<R>, Self::Error>;
328
329 fn peek_quads<'p>(
330 &'p self,
331 pattern: LinearQuadPattern<&'p R>,
332 ) -> Result<DynQuadIterator<'p, R, Self::Error>, Self::Error>
333 where
334 R: 'p;
335
336 fn deserialize_quad<'p>(
337 &mut self,
338 pattern: LinearQuadPattern<&'p R>,
339 ) -> Result<Option<Quad<R>>, Self::Error>
340 where
341 R: 'p;
342}
343
344pub type DynTermIterator<'a, E> = Box<dyn 'a + Iterator<Item = Result<CowTerm<'a>, E>>>;
346
347pub type DynResourceIterator<'a, R, E> = Box<dyn 'a + Iterator<Item = Result<&'a R, E>>>;
349
350pub type DynQuadIterator<'a, R, E> = Box<dyn 'a + Iterator<Item = Result<Quad<&'a R>, E>>>;
352
353impl<'d, R, E> LinkedDataDeserializer<R> for dyn 'd + DynLinkedDataDeserializer<R, Error = E>
354where
355 E: Error<R>,
356{
357 type Error = E;
358
359 fn interpret(&mut self, term: CowTerm) -> Result<R, Self::Error> {
360 DynLinkedDataDeserializer::interpret(self, term)
361 }
362
363 fn terms_of<'a>(
364 &'a self,
365 resource: &'a R,
366 ) -> Result<impl Iterator<Item = Result<CowTerm<'a>, Self::Error>>, Self::Error> {
367 DynLinkedDataDeserializer::terms_of(self, resource)
368 }
369
370 fn peek_resources<'a>(
371 &'a self,
372 ) -> Result<impl Iterator<Item = Result<&'a R, Self::Error>>, Self::Error>
373 where
374 R: 'a,
375 {
376 DynLinkedDataDeserializer::peek_resources(self)
377 }
378
379 fn deserialize_resource(&mut self, resource: Option<R>) -> Result<Option<R>, Self::Error> {
380 DynLinkedDataDeserializer::deserialize_resource(self, resource)
381 }
382
383 fn peek_quads<'p>(
384 &'p self,
385 pattern: impl Into<LinearQuadPattern<&'p R>>,
386 ) -> Result<impl Iterator<Item = Result<Quad<&'p R>, Self::Error>>, Self::Error>
387 where
388 R: 'p,
389 {
390 DynLinkedDataDeserializer::peek_quads(self, pattern.into())
391 }
392
393 fn deserialize_quad<'p>(
394 &mut self,
395 pattern: impl Into<LinearQuadPattern<&'p R>>,
396 ) -> Result<Option<Quad<R>>, Self::Error>
397 where
398 R: 'p,
399 {
400 DynLinkedDataDeserializer::deserialize_quad(self, pattern.into())
401 }
402}
403
404impl<R, D> DynLinkedDataDeserializer<R> for D
405where
406 D: LinkedDataDeserializer<R>,
407{
408 type Error = D::Error;
409
410 fn interpret(&mut self, term: CowTerm) -> Result<R, Self::Error> {
411 LinkedDataDeserializer::interpret(self, term)
412 }
413
414 fn terms_of<'a>(
415 &'a self,
416 resource: &'a R,
417 ) -> Result<Box<dyn 'a + Iterator<Item = Result<CowTerm<'a>, Self::Error>>>, Self::Error> {
418 LinkedDataDeserializer::terms_of(self, resource).map(|i| Box::new(i) as _)
419 }
420
421 fn peek_resources<'a>(
422 &'a self,
423 ) -> Result<Box<dyn 'a + Iterator<Item = Result<&'a R, Self::Error>>>, Self::Error>
424 where
425 R: 'a,
426 {
427 LinkedDataDeserializer::peek_resources(self).map(|i| Box::new(i) as _)
428 }
429
430 fn deserialize_resource(&mut self, resource: Option<R>) -> Result<Option<R>, Self::Error> {
431 LinkedDataDeserializer::deserialize_resource(self, resource)
432 }
433
434 fn peek_quads<'p>(
435 &'p self,
436 pattern: LinearQuadPattern<&'p R>,
437 ) -> Result<Box<dyn 'p + Iterator<Item = Result<Quad<&'p R>, Self::Error>>>, Self::Error>
438 where
439 R: 'p,
440 {
441 LinkedDataDeserializer::peek_quads(self, pattern).map(|i| Box::new(i) as _)
442 }
443
444 fn deserialize_quad<'p>(
445 &mut self,
446 pattern: LinearQuadPattern<&'p R>,
447 ) -> Result<Option<Quad<R>>, Self::Error>
448 where
449 R: 'p,
450 {
451 LinkedDataDeserializer::deserialize_quad(self, pattern)
452 }
453}
454
455impl<R, S: ?Sized + LinkedDataDeserializer<R>> LinkedDataDeserializer<R> for &mut S {
456 type Error = S::Error;
457
458 fn interpret(&mut self, term: CowTerm) -> Result<R, Self::Error> {
459 S::interpret(*self, term)
460 }
461
462 fn terms_of<'a>(
463 &'a self,
464 resource: &'a R,
465 ) -> Result<impl Iterator<Item = Result<CowTerm<'a>, Self::Error>>, Self::Error> {
466 S::terms_of(*self, resource)
467 }
468
469 fn peek_resources<'a>(
470 &'a self,
471 ) -> Result<impl Iterator<Item = Result<&'a R, Self::Error>>, Self::Error>
472 where
473 R: 'a,
474 {
475 S::peek_resources(*self)
476 }
477
478 fn deserialize_resource(&mut self, resource: Option<R>) -> Result<Option<R>, Self::Error> {
479 S::deserialize_resource(*self, resource)
480 }
481
482 fn peek_quads<'p>(
483 &'p self,
484 pattern: impl Into<LinearQuadPattern<&'p R>>,
485 ) -> Result<impl Iterator<Item = Result<Quad<&'p R>, Self::Error>>, Self::Error>
486 where
487 R: 'p,
488 {
489 S::peek_quads(*self, pattern)
490 }
491
492 fn deserialize_quad<'p>(
493 &mut self,
494 pattern: impl Into<LinearQuadPattern<&'p R>>,
495 ) -> Result<Option<Quad<R>>, Self::Error>
496 where
497 R: 'p,
498 {
499 S::deserialize_quad(*self, pattern)
500 }
501}
502
503pub trait Error<R>: Sized + Debug + Display {
504 fn custom(str: impl ToString) -> Self;
505
506 fn missing_resource() -> Self {
507 Self::custom("missing resouce")
508 }
509
510 fn unexpected_resource(_resource: &R) -> Self {
511 Self::custom("unexpected resource")
512 }
513
514 fn missing_quad() -> Self {
515 Self::custom("missing quad")
516 }
517}