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}