rdf_types/dataset/
mod.rs

1//! Dataset traits and implementations.
2use crate::{
3	pattern::{quad::canonical::PatternGraph, CanonicalQuadPattern},
4	utils::{OptionIterator, TripleToQuadIterator},
5	Quad,
6};
7
8pub mod fallible;
9pub use fallible::FallibleDataset;
10
11mod graph;
12pub use graph::{fallible as fallible_graph, *};
13
14mod r#impl;
15pub use r#impl::*;
16
17pub mod isomorphism;
18
19/// RDF dataset.
20pub trait Dataset {
21	/// Resource type.
22	type Resource;
23}
24
25impl<G: Graph> Dataset for G {
26	type Resource = G::Resource;
27}
28
29/// Dataset that can be traversed using a provided quad iterator.
30pub trait TraversableDataset: Dataset {
31	/// Quads iterator.
32	type Quads<'a>: Iterator<Item = Quad<&'a Self::Resource>>
33	where
34		Self: 'a;
35
36	/// Returns an iterator over the quads of the dataset.
37	fn quads(&self) -> Self::Quads<'_>;
38
39	fn quads_count(&self) -> usize {
40		self.quads().count()
41	}
42}
43
44impl<G: TraversableGraph> TraversableDataset for G {
45	type Quads<'a>
46		= TripleToQuadIterator<G::Triples<'a>, &'a G::Resource>
47	where
48		Self: 'a;
49
50	fn quads(&self) -> Self::Quads<'_> {
51		TripleToQuadIterator::new(self.triples())
52	}
53
54	fn quads_count(&self) -> usize {
55		TraversableGraph::triples_count(self)
56	}
57}
58
59pub trait ResourceTraversableDataset: Dataset {
60	type Resources<'a>: Iterator<Item = &'a Self::Resource>
61	where
62		Self: 'a;
63
64	fn resources(&self) -> Self::Resources<'_>;
65
66	fn resource_count(&self) -> usize {
67		self.resources().count()
68	}
69}
70
71impl<G: ResourceTraversableGraph> ResourceTraversableDataset for G {
72	type Resources<'a>
73		= G::GraphResources<'a>
74	where
75		Self: 'a;
76
77	fn resources(&self) -> Self::Resources<'_> {
78		self.graph_resources()
79	}
80
81	fn resource_count(&self) -> usize {
82		self.graph_resource_count()
83	}
84}
85
86pub trait SubjectTraversableDataset: Dataset {
87	type Subjects<'a>: Iterator<Item = &'a Self::Resource>
88	where
89		Self: 'a;
90
91	fn subjects(&self) -> Self::Subjects<'_>;
92
93	fn subject_count(&self) -> usize {
94		self.subjects().count()
95	}
96}
97
98impl<G: SubjectTraversableGraph> SubjectTraversableDataset for G {
99	type Subjects<'a>
100		= G::GraphSubjects<'a>
101	where
102		Self: 'a;
103
104	fn subjects(&self) -> Self::Subjects<'_> {
105		self.graph_subjects()
106	}
107
108	fn subject_count(&self) -> usize {
109		self.graph_subject_count()
110	}
111}
112
113pub trait PredicateTraversableDataset: Dataset {
114	type Predicates<'a>: Iterator<Item = &'a Self::Resource>
115	where
116		Self: 'a;
117
118	fn predicates(&self) -> Self::Predicates<'_>;
119
120	fn predicate_count(&self) -> usize {
121		self.predicates().count()
122	}
123}
124
125impl<G: PredicateTraversableGraph> PredicateTraversableDataset for G {
126	type Predicates<'a>
127		= G::GraphPredicates<'a>
128	where
129		Self: 'a;
130
131	fn predicates(&self) -> Self::Predicates<'_> {
132		self.graph_predicates()
133	}
134
135	fn predicate_count(&self) -> usize {
136		self.graph_predicate_count()
137	}
138}
139
140pub trait ObjectTraversableDataset: Dataset {
141	type Objects<'a>: Iterator<Item = &'a Self::Resource>
142	where
143		Self: 'a;
144
145	fn objects(&self) -> Self::Objects<'_>;
146
147	fn object_count(&self) -> usize {
148		self.objects().count()
149	}
150}
151
152impl<G: ObjectTraversableGraph> ObjectTraversableDataset for G {
153	type Objects<'a>
154		= G::GraphObjects<'a>
155	where
156		Self: 'a;
157
158	fn objects(&self) -> Self::Objects<'_> {
159		self.graph_objects()
160	}
161
162	fn object_count(&self) -> usize {
163		self.graph_object_count()
164	}
165}
166
167pub trait NamedGraphTraversableDataset: Dataset {
168	type NamedGraphs<'a>: Iterator<Item = &'a Self::Resource>
169	where
170		Self: 'a;
171
172	fn named_graphs(&self) -> Self::NamedGraphs<'_>;
173
174	fn named_graph_count(&self) -> usize {
175		self.named_graphs().count()
176	}
177}
178
179impl<G: Graph> NamedGraphTraversableDataset for G {
180	type NamedGraphs<'a>
181		= std::iter::Empty<&'a Self::Resource>
182	where
183		Self: 'a;
184
185	fn named_graphs(&self) -> Self::NamedGraphs<'_> {
186		std::iter::empty()
187	}
188
189	fn named_graph_count(&self) -> usize {
190		0
191	}
192}
193
194/// Pattern-matching-capable dataset.
195pub trait PatternMatchingDataset: Dataset {
196	/// Pattern-matching iterator.
197	type QuadPatternMatching<'a, 'p>: Iterator<Item = Quad<&'a Self::Resource>>
198	where
199		Self: 'a,
200		Self::Resource: 'p;
201
202	/// Returns an iterator over all the quads of the dataset matching the given
203	/// pattern.
204	fn quad_pattern_matching<'p>(
205		&self,
206		pattern: CanonicalQuadPattern<&'p Self::Resource>,
207	) -> Self::QuadPatternMatching<'_, 'p>;
208
209	/// Checks if the dataset contains the given quad.
210	fn contains_quad(&self, quad: Quad<&Self::Resource>) -> bool {
211		self.quad_pattern_matching(quad.into()).next().is_some()
212	}
213
214	/// Checks if the dataset contains the given subject.
215	fn contains_quad_subject(&self, subject: &Self::Resource) -> bool {
216		use crate::pattern::quad::canonical::{
217			GivenSubject, GivenSubjectAnyPredicate, GivenSubjectAnyPredicateAnyObject,
218		};
219		self.quad_pattern_matching(CanonicalQuadPattern::GivenSubject(
220			subject,
221			GivenSubject::AnyPredicate(GivenSubjectAnyPredicate::AnyObject(
222				GivenSubjectAnyPredicateAnyObject::AnyGraph,
223			)),
224		))
225		.next()
226		.is_some()
227	}
228
229	/// Checks if the dataset contains the given predicate.
230	fn contains_quad_predicate(&self, predicate: &Self::Resource) -> bool {
231		use crate::pattern::quad::canonical::{
232			AnySubject, AnySubjectGivenPredicate, AnySubjectGivenPredicateAnyObject,
233		};
234		self.quad_pattern_matching(CanonicalQuadPattern::AnySubject(
235			AnySubject::GivenPredicate(
236				predicate,
237				AnySubjectGivenPredicate::AnyObject(AnySubjectGivenPredicateAnyObject::AnyGraph),
238			),
239		))
240		.next()
241		.is_some()
242	}
243
244	/// Checks if the dataset contains the given object.
245	fn contains_quad_object(&self, object: &Self::Resource) -> bool {
246		use crate::pattern::quad::canonical::{
247			AnySubject, AnySubjectAnyPredicate, AnySubjectAnyPredicateGivenObject,
248		};
249		self.quad_pattern_matching(CanonicalQuadPattern::AnySubject(AnySubject::AnyPredicate(
250			AnySubjectAnyPredicate::GivenObject(
251				object,
252				AnySubjectAnyPredicateGivenObject::AnyGraph,
253			),
254		)))
255		.next()
256		.is_some()
257	}
258
259	/// Checks if the dataset contains the given named graph.
260	fn contains_named_graph(&self, named_graph: &Self::Resource) -> bool {
261		use crate::pattern::quad::canonical::{
262			AnySubject, AnySubjectAnyPredicate, AnySubjectAnyPredicateAnyObject,
263		};
264		self.quad_pattern_matching(CanonicalQuadPattern::AnySubject(AnySubject::AnyPredicate(
265			AnySubjectAnyPredicate::AnyObject(AnySubjectAnyPredicateAnyObject::GivenGraph(Some(
266				named_graph,
267			))),
268		)))
269		.next()
270		.is_some()
271	}
272
273	/// Returns an iterator over all the predicates `p` matching any quad
274	/// `subject p o graph` present in the dataset, for any object `o`.
275	fn quad_predicates_objects<'p>(
276		&self,
277		graph: Option<&'p Self::Resource>,
278		subject: &'p Self::Resource,
279	) -> QuadPredicatesObjects<'_, 'p, Self>
280	where
281		Self: PredicateTraversableDataset,
282	{
283		QuadPredicatesObjects {
284			graph,
285			subject,
286			predicates: self.predicates(),
287			dataset: self,
288		}
289	}
290
291	/// Returns an iterator over all the objects `o` matching the quad `subject predicate o graph`.
292	fn quad_objects<'p>(
293		&self,
294		graph: Option<&'p Self::Resource>,
295		subject: &'p Self::Resource,
296		predicate: &'p Self::Resource,
297	) -> QuadObjects<'_, 'p, Self> {
298		QuadObjects {
299			first: None,
300			inner: self.quad_pattern_matching(CanonicalQuadPattern::from_option_quad(Quad(
301				Some(subject),
302				Some(predicate),
303				None,
304				Some(graph),
305			))),
306		}
307	}
308}
309
310impl<G: PatternMatchingGraph> PatternMatchingDataset for G {
311	type QuadPatternMatching<'a, 'p>
312		= OptionIterator<TripleToQuadIterator<G::TriplePatternMatching<'a, 'p>, &'a G::Resource>>
313	where
314		Self: 'a,
315		Self::Resource: 'p;
316
317	fn quad_pattern_matching<'p>(
318		&self,
319		pattern: CanonicalQuadPattern<&'p Self::Resource>,
320	) -> Self::QuadPatternMatching<'_, 'p> {
321		let (pattern, g) = pattern.into_triple();
322		match g {
323			PatternGraph::Given(None) | PatternGraph::Any => OptionIterator(Some(
324				TripleToQuadIterator::new(self.triple_pattern_matching(pattern)),
325			)),
326			_ => OptionIterator(None),
327		}
328	}
329}
330
331pub struct QuadPredicatesObjects<
332	'a,
333	'p,
334	D: 'a + ?Sized + PredicateTraversableDataset + PatternMatchingDataset,
335> {
336	graph: Option<&'p D::Resource>,
337	subject: &'p D::Resource,
338	predicates: D::Predicates<'a>,
339	dataset: &'a D,
340}
341
342impl<'a: 'p, 'p, D: 'a + ?Sized + PredicateTraversableDataset + PatternMatchingDataset> Iterator
343	for QuadPredicatesObjects<'a, 'p, D>
344where
345	D::Resource: 'p,
346{
347	type Item = (&'a D::Resource, QuadObjects<'p, 'p, D>);
348
349	fn next(&mut self) -> Option<Self::Item> {
350		for predicate in &mut self.predicates {
351			use crate::pattern::quad::canonical::{
352				GivenSubject, GivenSubjectGivenPredicate, GivenSubjectGivenPredicateAnyObject,
353			};
354			let pattern = CanonicalQuadPattern::GivenSubject(
355				self.subject,
356				GivenSubject::GivenPredicate(
357					predicate,
358					GivenSubjectGivenPredicate::AnyObject(
359						GivenSubjectGivenPredicateAnyObject::GivenGraph(self.graph),
360					),
361				),
362			);
363
364			let mut iter = self.dataset.quad_pattern_matching(pattern);
365			if let Some(Quad(_, _, o, _)) = iter.next() {
366				return Some((
367					predicate,
368					QuadObjects {
369						first: Some(o),
370						inner: iter,
371					},
372				));
373			}
374		}
375
376		None
377	}
378}
379
380pub struct QuadObjects<'a, 'p, D: 'a + ?Sized + PatternMatchingDataset>
381where
382	D::Resource: 'p,
383{
384	first: Option<&'a D::Resource>,
385	inner: D::QuadPatternMatching<'a, 'p>,
386}
387
388impl<'a, 'p, D: 'a + ?Sized + PatternMatchingDataset> Iterator for QuadObjects<'a, 'p, D>
389where
390	D::Resource: 'p,
391{
392	type Item = &'a D::Resource;
393
394	fn next(&mut self) -> Option<Self::Item> {
395		self.first
396			.take()
397			.or_else(|| self.inner.next().map(Quad::into_object))
398	}
399}
400
401/// Mutable dataset.
402pub trait DatasetMut: Dataset {
403	/// Inserts the given quad in the dataset.
404	fn insert(&mut self, quad: Quad<Self::Resource>);
405
406	/// Removes the given quad from the dataset.
407	fn remove(&mut self, quad: Quad<&Self::Resource>);
408}
409
410/// Dataset view focusing on a given graph.
411pub struct DatasetView<'a, D: Dataset> {
412	pub dataset: &'a D,
413	pub graph: Option<&'a D::Resource>,
414}
415
416/// Dataset view focusing on a given resource and restricted to the given graph.
417pub struct DatasetGraphView<'a, D: Dataset> {
418	pub dataset: &'a D,
419	pub graph: Option<&'a D::Resource>,
420	pub resource: &'a D::Resource,
421}