Skip to main content

grdf/
lib.rs

1//! The [Resource Description Framework (RDF)](https://en.wikipedia.org/wiki/Resource_Description_Framework)
2//! is a powerful method for modeling data and knowledge
3//! defined by the [World Wide Web Consortium (W3C)](https://www.w3.org/).
4//! A RDF dataset consists in a collection of graphs connecting nodes, values
5//! and predicates. This crate provides traits and implementations of
6//! [Generalized RDF (gRDF)](https://www.w3.org/TR/2014/REC-rdf11-concepts-20140225/#section-generalized-rdf)
7//! where nodes, values and predicates have the same representation.
8//!
9//! Note that this crates requires rust compiler version 1.65 or later.
10//! It needs Generic Associated Typed (GAT) to work properly.
11//!
12//! ## Basic usage
13//!
14//! ### Exploring a dataset
15//!
16//! Each `Dataset` implementation provides many iterators to explore the data.
17//! One simple way is to iterate through the quad of the dataset:
18//!
19//! ```rust
20//! # use rdf_types::{Term, Quad};
21//! # use grdf::HashDataset;
22//! # let dataset: HashDataset<Term> = HashDataset::new();
23//! for Quad(subject, predicate, object, graph) in dataset {
24//!   // do something
25//! }
26//! ```
27//!
28//! Another way is to access each graph individually using `Dataset::graph`.
29//! For a given graph, it is then possible to iterate through the triples of the
30//! graph:
31//!
32//! ```rust
33//! # use rdf_types::{Term, Triple};
34//! # use grdf::HashDataset;
35//! # let dataset: HashDataset<Term> = HashDataset::new();
36//! # let id: Option<&Term> = None;
37//! let graph = dataset.graph(id).unwrap();
38//!
39//! for Triple(subject, predicate, object) in graph {
40//!   // do something
41//! }
42//! ```
43//!
44//! It is also possible to explore the graph logically, subject by subject,
45//! predicate by predicate, object by object:
46//!
47//! ```rust
48//! # use rdf_types::Term;
49//! # use grdf::HashGraph;
50//! # let graph: HashGraph<Term> = HashGraph::new();
51//! // for each subject of the graph...
52//! for (subject, predicates) in graph.subjects() {
53//!   // for each predicate it is subject...
54//!   for (predicate, objects) in predicates {
55//!     // for each triple (subject, predicate, object)...
56//!     for object in objects {
57//!       // do something
58//!     }
59//!   }
60//! }
61//! ```
62//!
63//! ### Inserting new data
64//!
65//! Insertion can be done on `MutableDataset` implementations using
66//! `MutableDataset::insert`:
67//!
68//! ```rust
69//! # use rdf_types::{Id, Term, Quad, BlankIdBuf};
70//! # use grdf::HashDataset;
71//! # let graph = None;
72//! # let subject = Term::Id(Id::Blank(BlankIdBuf::from_u8(0)));
73//! # let predicate = Term::Id(Id::Blank(BlankIdBuf::from_u8(1)));
74//! # let object = Term::Id(Id::Blank(BlankIdBuf::from_u8(2)));
75//! let mut dataset: HashDataset<Term> = HashDataset::new();
76//! dataset.insert(Quad(subject, predicate, object, graph));
77//! ```
78//!
79//! Again it is possible to access each graph of the dataset mutably:
80//!
81//! ```rust
82//! # use rdf_types::{Id, Term, Triple, BlankIdBuf};
83//! # use grdf::{MutableDataset, MutableGraph, HashDataset};
84//! # let id: Option<&Term> = None;
85//! # let subject = Term::Id(Id::Blank(BlankIdBuf::from_u8(0)));
86//! # let predicate = Term::Id(Id::Blank(BlankIdBuf::from_u8(1)));
87//! # let object = Term::Id(Id::Blank(BlankIdBuf::from_u8(2)));
88//! # let mut dataset: HashDataset<Term> = HashDataset::new();
89//! let mut graph = dataset.graph_mut(id).unwrap();
90//! graph.insert(Triple(subject, predicate, object));
91//! ```
92//!
93//! ### Custom RDF types
94//!
95//! The types used to represent RDF subjects, predicate and objects are
96//! parameters of the dataset. Anything can be used although they default to the
97//! `rdf_types::Term` type that represents generic RDF nodes (blank nodes,
98//! IRI-named nodes and literal values).
99pub use rdf_types::{Quad, Triple};
100
101mod graph;
102mod r#impl;
103pub mod macros;
104pub mod utils;
105mod view;
106
107#[cfg(feature = "meta")]
108pub mod meta;
109
110pub use graph::*;
111pub use r#impl::*;
112pub use view::*;
113
114/// gRDF dataset.
115///
116/// A dataset is a collection of graphs.
117/// It is made of a default graph and a collection of named graphs.
118///
119/// A dataset can also be seen as a collection of [`Quad`]s.
120pub trait Dataset {
121	type Subject;
122	type Predicate;
123	type Object;
124	type GraphLabel;
125
126	/// Type of graphs in the dataset.
127	type Graph: Graph<Subject = Self::Subject, Predicate = Self::Predicate, Object = Self::Object>;
128
129	/// Graph iterator.
130	///
131	/// Each graph is associated to its name (if any).
132	type Graphs<'a>: Iterator<Item = (Option<&'a Self::GraphLabel>, &'a Self::Graph)>
133	where
134		Self: 'a;
135
136	/// Quads iterator.
137	type Quads<'a>: Iterator<
138		Item = Quad<&'a Self::Subject, &'a Self::Predicate, &'a Self::Object, &'a Self::GraphLabel>,
139	> where
140		Self: 'a;
141
142	type PatternMatching<'a, 'p>: Iterator<
143		Item = Quad<&'a Self::Subject, &'a Self::Predicate, &'a Self::Object, &'a Self::GraphLabel>,
144	> where
145		Self: 'a,
146		Self::Subject: 'p,
147		Self::Predicate: 'p,
148		Self::Object: 'p,
149		Self::GraphLabel: 'p;
150
151	/// Get the graph with the given name.
152	/// Input `None` to get the default graph.
153	fn graph(&self, id: Option<&Self::GraphLabel>) -> Option<&Self::Graph>;
154
155	/// Get the default graph of the dataset.
156	///
157	/// This is the same as `graph(None)`.
158	fn default_graph(&self) -> &Self::Graph {
159		self.graph(None).unwrap()
160	}
161
162	/// Returns an iterator over the graphs of the dataset.
163	fn graphs(&self) -> Self::Graphs<'_>;
164
165	/// Returns an iterator over the quads of the dataset.
166	fn quads(&self) -> Self::Quads<'_>;
167
168	/// Returns the number of quads in the dataset.
169	fn len(&self) -> usize {
170		let mut len = 0;
171
172		for (_, g) in self.graphs() {
173			len += g.len()
174		}
175
176		len
177	}
178
179	/// Checks is the dataset is empty.
180	fn is_empty(&self) -> bool {
181		for (_, g) in self.graphs() {
182			if !g.is_empty() {
183				return false;
184			}
185		}
186
187		true
188	}
189
190	/// Iterate through all the subjects of the given graph.
191	fn subjects<'a>(
192		&'a self,
193		id: Option<&Self::GraphLabel>,
194	) -> Option<<Self::Graph as Graph>::Subjects<'a>>
195	where
196		Self::Graph: 'a,
197		Self::Subject: 'a,
198		Self::Predicate: 'a,
199		Self::Object: 'a,
200	{
201		self.graph(id).map(|graph| graph.subjects())
202	}
203
204	/// Creates a view for the dataset, using the given subject from the given
205	/// graph.
206	fn view<'a, A>(
207		&'a self,
208		graph_label: Option<&'a Self::GraphLabel>,
209		subject: &'a Self::Subject,
210		access: A,
211	) -> View<Self, A> {
212		View::new(self, graph_label, self.graph(graph_label), subject, access)
213	}
214
215	/// Iterate through all the predicates of the given subject of the given
216	/// graph.
217	fn predicates<'a>(
218		&'a self,
219		id: Option<&Self::GraphLabel>,
220		subject: &Self::Subject,
221	) -> Option<<Self::Graph as Graph>::Predicates<'a>>
222	where
223		Self::Graph: 'a,
224		Self::Predicate: 'a,
225		Self::Object: 'a,
226	{
227		self.graph(id).map(|graph| graph.predicates(subject))
228	}
229
230	/// Iterate through all the objects of the given subject and predicate of the
231	/// given graph.
232	fn objects<'a>(
233		&'a self,
234		id: Option<&Self::GraphLabel>,
235		subject: &Self::Subject,
236		predicate: &Self::Predicate,
237	) -> Option<<Self::Graph as Graph>::Objects<'a>>
238	where
239		Self::Graph: 'a,
240		Self::Object: 'a,
241	{
242		self.graph(id)
243			.map(|graph| graph.objects(subject, predicate))
244	}
245
246	/// Checks if the given quad is defined in the dataset.
247	#[allow(clippy::type_complexity)]
248	fn contains(
249		&self,
250		Quad(s, p, o, g): Quad<&Self::Subject, &Self::Predicate, &Self::Object, &Self::GraphLabel>,
251	) -> bool {
252		match self.graph(g) {
253			Some(g) => g.contains(Triple(s, p, o)),
254			None => false,
255		}
256	}
257
258	#[allow(clippy::type_complexity)]
259	fn pattern_matching<'p>(
260		&self,
261		pattern: Quad<
262			Option<&'p Self::Subject>,
263			Option<&'p Self::Predicate>,
264			Option<&'p Self::Object>,
265			Option<&'p Self::GraphLabel>,
266		>,
267	) -> Self::PatternMatching<'_, 'p>;
268
269	#[allow(clippy::type_complexity)]
270	fn any_match(
271		&self,
272		pattern: Quad<
273			Option<&Self::Subject>,
274			Option<&Self::Predicate>,
275			Option<&Self::Object>,
276			Option<&Self::GraphLabel>,
277		>,
278	) -> Option<Quad<&Self::Subject, &Self::Predicate, &Self::Object, &Self::GraphLabel>> {
279		self.pattern_matching(pattern).next()
280	}
281
282	#[allow(clippy::type_complexity)]
283	#[deprecated = "use `any_match` instead"]
284	fn first_match(
285		&self,
286		pattern: Quad<
287			Option<&Self::Subject>,
288			Option<&Self::Predicate>,
289			Option<&Self::Object>,
290			Option<&Self::GraphLabel>,
291		>,
292	) -> Option<Quad<&Self::Subject, &Self::Predicate, &Self::Object, &Self::GraphLabel>> {
293		self.any_match(pattern)
294	}
295}
296
297/// Sized gRDF dataset that can be converted into iterators.
298pub trait SizedDataset: Dataset + Sized
299where
300	Self::Graph: SizedGraph,
301{
302	/// Consuming graphs iterator.
303	type IntoGraphs: Iterator<Item = (Option<Self::GraphLabel>, Self::Graph)>;
304
305	/// Consuming quads iterator.
306	type IntoQuads: Iterator<
307		Item = Quad<Self::Subject, Self::Predicate, Self::Object, Self::GraphLabel>,
308	>;
309
310	/// Consumes the dataset and returns the given graph.
311	fn into_graph(self, id: Option<&Self::GraphLabel>) -> Option<Self::Graph>;
312
313	/// Consumes the dataset and returns the default graph.
314	fn into_default_graph(self) -> Self::Graph {
315		self.into_graph(None).unwrap()
316	}
317
318	/// Consumes the dataset and returns an iterator over its graphs.
319	fn into_graphs(self) -> Self::IntoGraphs;
320
321	/// Consumes the dataset and returns an iterator over its quads.
322	fn into_quads(self) -> Self::IntoQuads;
323
324	/// Consumes the dataset and returns an iterator over the subjects of the
325	/// given graph.
326	fn into_subjects(
327		self,
328		id: Option<&Self::GraphLabel>,
329	) -> Option<<Self::Graph as SizedGraph>::IntoSubjects> {
330		self.into_graph(id).map(|graph| graph.into_subjects())
331	}
332
333	/// Consumes the dataset and returns an iterator over the predicates of the
334	/// given subject of the given graph.
335	fn into_predicates(
336		self,
337		id: Option<&Self::GraphLabel>,
338		subject: &Self::Subject,
339	) -> Option<<Self::Graph as SizedGraph>::IntoPredicates> {
340		self.into_graph(id)
341			.map(|graph| graph.into_predicates(subject))
342	}
343
344	/// Consumes the dataset and returns an iterator over the objects of the
345	/// given subject and predicate of the given graph.
346	fn into_objects(
347		self,
348		id: Option<&Self::GraphLabel>,
349		subject: &Self::Subject,
350		predicate: &Self::Predicate,
351	) -> Option<<Self::Graph as SizedGraph>::IntoObjects> {
352		self.into_graph(id)
353			.map(|graph| graph.into_objects(subject, predicate))
354	}
355}
356
357/// Mutable dataset.
358pub trait MutableDataset: Dataset {
359	/// Iterator over mutable graphs.
360	type GraphsMut<'a>: Iterator<Item = (Option<&'a Self::GraphLabel>, &'a mut Self::Graph)>
361	where
362		Self: 'a;
363
364	// type Drain<'a>: 'a + Iterator<Item = Quad<Self::Subject, Self::Predicate, Self::Object, Self::Graph>> where Self: 'a;
365
366	// type DrainFilter<'a, F>: 'a + Iterator<Item = Quad<Self::Subject, Self::Predicate, Self::Object, Self::Graph>> where Self: 'a;
367
368	// type DrainPatternMatching<'a>: 'a + Iterator<Item = Quad<Self::Subject, Self::Predicate, Self::Object, Self::Graph>> where Self: 'a;
369
370	/// Get the given graph mutably.
371	///
372	/// Use the input `None` to get the default graph.
373	///
374	/// Note to implementors: the default graph should always exists.
375	fn graph_mut(&mut self, id: Option<&Self::GraphLabel>) -> Option<&mut Self::Graph>;
376
377	/// Get the default graph mutably.
378	///
379	/// Note to implementors: the default graph should always exists.
380	fn default_graph_mut(&mut self) -> &mut Self::Graph {
381		self.graph_mut(None).unwrap()
382	}
383
384	/// Returns an iterator over the (mutable) graphs of the dataset.
385	fn graphs_mut(&mut self) -> Self::GraphsMut<'_>;
386
387	/// Insert a graph in the dataset with the given name.
388	///
389	/// If a graph with the given name already exists,
390	/// it is replaced and the previous graph definition is returned.
391	fn insert_graph(&mut self, id: Self::GraphLabel, graph: Self::Graph) -> Option<Self::Graph>;
392
393	/// Insert a quad in the dataset.
394	fn insert(
395		&mut self,
396		quad: Quad<Self::Subject, Self::Predicate, Self::Object, Self::GraphLabel>,
397	) -> bool;
398
399	/// Remove a quad from the dataset.
400	fn remove(
401		&mut self,
402		quad: Quad<&Self::Subject, &Self::Predicate, &Self::Object, &Self::GraphLabel>,
403	);
404
405	// fn drain(&mut self) -> Self::Drain<'_>;
406
407	// fn drain_filter<F>(&mut self, pred: F) -> Self::DrainFilter<'_, F>;
408
409	// fn drain_pattern_matching(
410	// 	&mut self,
411	// 	pattern: Quad<Option<&Self::Subject>, Option<&Self::Predicate>, Option<&Self::Object>, Option<&Self::GraphLabel>>
412	// ) -> Self::DrainPatternMatching<'_>;
413
414	/// Absorb the given other dataset.
415	///
416	/// Adds all the quads of `other` in the dataset.
417	fn absorb<
418		D: SizedDataset<
419			Subject = Self::Subject,
420			Predicate = Self::Predicate,
421			Object = Self::Object,
422			GraphLabel = Self::GraphLabel,
423		>,
424	>(
425		&mut self,
426		other: D,
427	) where
428		D::Graph: SizedGraph;
429}
430
431pub trait DatasetTake<
432	T: ?Sized = <Self as Dataset>::Subject,
433	U: ?Sized = <Self as Dataset>::Predicate,
434	V: ?Sized = <Self as Dataset>::Object,
435	W: ?Sized = <Self as Dataset>::GraphLabel,
436>: MutableDataset where
437	Self::Graph: GraphTake,
438{
439	#[allow(clippy::type_complexity)]
440	fn take(
441		&mut self,
442		quad: Quad<&T, &U, &V, &W>,
443	) -> Option<Quad<Self::Subject, Self::Predicate, Self::Object, Self::GraphLabel>>;
444
445	#[allow(clippy::type_complexity)]
446	fn take_match(
447		&mut self,
448		quad: Quad<Option<&T>, Option<&U>, Option<&V>, Option<&W>>,
449	) -> Option<Quad<Self::Subject, Self::Predicate, Self::Object, Self::GraphLabel>>;
450}