Skip to main content

linked_data/de/
mod.rs

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
312/// Dyn-compatible version of `LinkedDataDeserializer`.
313pub 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
344/// Boxed type-erased term iterator.
345pub type DynTermIterator<'a, E> = Box<dyn 'a + Iterator<Item = Result<CowTerm<'a>, E>>>;
346
347/// Boxed type-erased resource iterator.
348pub type DynResourceIterator<'a, R, E> = Box<dyn 'a + Iterator<Item = Result<&'a R, E>>>;
349
350/// Boxed type-erased quad iterator.
351pub 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}