1use crate::interning::*;
33use crate::*;
34#[cfg(feature = "rdfc-10")]
35use sha2::{Digest, Sha256, Sha384};
36use std::collections::hash_map::Entry;
37use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
38use std::fmt;
39use std::hash::{DefaultHasher, Hash, Hasher};
40use std::mem::take;
41
42#[derive(Debug, Default, Clone)]
70pub struct Dataset {
71 interner: Interner,
72 gspo: BTreeSet<(
73 InternedGraphName,
74 InternedNamedOrBlankNode,
75 InternedNamedNode,
76 InternedTerm,
77 )>,
78 gpos: BTreeSet<(
79 InternedGraphName,
80 InternedNamedNode,
81 InternedTerm,
82 InternedNamedOrBlankNode,
83 )>,
84 gosp: BTreeSet<(
85 InternedGraphName,
86 InternedTerm,
87 InternedNamedOrBlankNode,
88 InternedNamedNode,
89 )>,
90 spog: BTreeSet<(
91 InternedNamedOrBlankNode,
92 InternedNamedNode,
93 InternedTerm,
94 InternedGraphName,
95 )>,
96 posg: BTreeSet<(
97 InternedNamedNode,
98 InternedTerm,
99 InternedNamedOrBlankNode,
100 InternedGraphName,
101 )>,
102 ospg: BTreeSet<(
103 InternedTerm,
104 InternedNamedOrBlankNode,
105 InternedNamedNode,
106 InternedGraphName,
107 )>,
108}
109
110impl Dataset {
111 pub fn new() -> Self {
113 Self::default()
114 }
115
116 pub fn graph<'a, 'b>(&'a self, graph_name: impl Into<GraphNameRef<'b>>) -> GraphView<'a> {
130 let graph_name = self
131 .encoded_graph_name(graph_name)
132 .unwrap_or_else(InternedGraphName::impossible);
133 GraphView {
134 dataset: self,
135 graph_name,
136 }
137 }
138
139 pub fn graph_mut<'a, 'b>(
161 &'a mut self,
162 graph_name: impl Into<GraphNameRef<'b>>,
163 ) -> GraphViewMut<'a> {
164 let graph_name = InternedGraphName::encoded_into(graph_name.into(), &mut self.interner);
165 GraphViewMut {
166 dataset: self,
167 graph_name,
168 }
169 }
170
171 pub fn iter(&self) -> Iter<'_> {
173 let iter = self.spog.iter();
174 Iter {
175 dataset: self,
176 inner: iter,
177 }
178 }
179
180 pub fn quads_for_subject<'a, 'b>(
181 &'a self,
182 subject: impl Into<NamedOrBlankNodeRef<'b>>,
183 ) -> impl Iterator<Item = QuadRef<'a>> + 'a {
184 let subject = self
185 .encoded_named_or_blank_node(subject)
186 .unwrap_or_else(InternedNamedOrBlankNode::impossible);
187 self.interned_quads_for_subject(&subject)
188 .map(move |q| self.decode_spog(q))
189 }
190
191 fn interned_quads_for_subject<'a>(
192 &'a self,
193 subject: &InternedNamedOrBlankNode,
194 ) -> impl Iterator<
195 Item = (
196 &'a InternedNamedOrBlankNode,
197 &'a InternedNamedNode,
198 &'a InternedTerm,
199 &'a InternedGraphName,
200 ),
201 > + use<'a> {
202 self.spog
203 .range(
204 &(
205 *subject,
206 InternedNamedNode::first(),
207 InternedTerm::first(),
208 InternedGraphName::first(),
209 )
210 ..&(
211 subject.next(),
212 InternedNamedNode::first(),
213 InternedTerm::first(),
214 InternedGraphName::first(),
215 ),
216 )
217 .map(|(s, p, o, g)| (s, p, o, g))
218 }
219
220 pub fn quads_for_predicate<'a, 'b>(
221 &'a self,
222 predicate: impl Into<NamedNodeRef<'b>>,
223 ) -> impl Iterator<Item = QuadRef<'a>> + 'a {
224 let predicate = self
225 .encoded_named_node(predicate)
226 .unwrap_or_else(InternedNamedNode::impossible);
227 self.interned_quads_for_predicate(predicate)
228 .map(move |q| self.decode_spog(q))
229 }
230
231 fn interned_quads_for_predicate(
232 &self,
233 predicate: InternedNamedNode,
234 ) -> impl Iterator<
235 Item = (
236 &InternedNamedOrBlankNode,
237 &InternedNamedNode,
238 &InternedTerm,
239 &InternedGraphName,
240 ),
241 > + '_ {
242 self.posg
243 .range(
244 &(
245 predicate,
246 InternedTerm::first(),
247 InternedNamedOrBlankNode::first(),
248 InternedGraphName::first(),
249 )
250 ..&(
251 predicate.next(),
252 InternedTerm::first(),
253 InternedNamedOrBlankNode::first(),
254 InternedGraphName::first(),
255 ),
256 )
257 .map(|(p, o, s, g)| (s, p, o, g))
258 }
259
260 pub fn quads_for_object<'a, 'b>(
261 &'a self,
262 object: impl Into<TermRef<'b>>,
263 ) -> impl Iterator<Item = QuadRef<'a>> + 'a {
264 let object = self
265 .encoded_term(object)
266 .unwrap_or_else(InternedTerm::impossible);
267
268 self.interned_quads_for_object(&object)
269 .map(move |q| self.decode_spog(q))
270 }
271
272 fn interned_quads_for_object<'a>(
273 &'a self,
274 object: &InternedTerm,
275 ) -> impl Iterator<
276 Item = (
277 &'a InternedNamedOrBlankNode,
278 &'a InternedNamedNode,
279 &'a InternedTerm,
280 &'a InternedGraphName,
281 ),
282 > + use<'a> {
283 self.ospg
284 .range(
285 &(
286 object.clone(),
287 InternedNamedOrBlankNode::first(),
288 InternedNamedNode::first(),
289 InternedGraphName::first(),
290 )
291 ..&(
292 object.next(),
293 InternedNamedOrBlankNode::first(),
294 InternedNamedNode::first(),
295 InternedGraphName::first(),
296 ),
297 )
298 .map(|(o, s, p, g)| (s, p, o, g))
299 }
300
301 pub fn quads_for_graph_name<'a, 'b>(
302 &'a self,
303 graph_name: impl Into<GraphNameRef<'b>>,
304 ) -> impl Iterator<Item = QuadRef<'a>> + 'a {
305 let graph_name = self
306 .encoded_graph_name(graph_name)
307 .unwrap_or_else(InternedGraphName::impossible);
308
309 self.interned_quads_for_graph_name(&graph_name)
310 .map(move |q| self.decode_spog(q))
311 }
312
313 fn interned_quads_for_graph_name<'a>(
314 &'a self,
315 graph_name: &InternedGraphName,
316 ) -> impl Iterator<
317 Item = (
318 &'a InternedNamedOrBlankNode,
319 &'a InternedNamedNode,
320 &'a InternedTerm,
321 &'a InternedGraphName,
322 ),
323 > + use<'a> {
324 self.gspo
325 .range(
326 &(
327 *graph_name,
328 InternedNamedOrBlankNode::first(),
329 InternedNamedNode::first(),
330 InternedTerm::first(),
331 )
332 ..&(
333 graph_name.next(),
334 InternedNamedOrBlankNode::first(),
335 InternedNamedNode::first(),
336 InternedTerm::first(),
337 ),
338 )
339 .map(|(g, s, p, o)| (s, p, o, g))
340 }
341
342 pub fn quads_for_pattern<'a>(
344 &'a self,
345 subject: Option<NamedOrBlankNodeRef<'a>>,
346 predicate: Option<NamedNodeRef<'a>>,
347 object: Option<TermRef<'a>>,
348 graph_name: Option<GraphNameRef<'a>>,
349 ) -> impl Iterator<Item = QuadRef<'a>> + 'a {
350 let iter: Box<dyn Iterator<Item = _>> = if let Some(subject) = subject {
351 Box::new(self.quads_for_subject(subject).filter(move |q| {
352 predicate.as_ref().is_none_or(|p| *p == q.predicate)
353 && object.as_ref().is_none_or(|o| *o == q.object)
354 && graph_name.as_ref().is_none_or(|g| *g == q.graph_name)
355 }))
356 } else if let Some(object) = object {
357 Box::new(self.quads_for_object(object).filter(move |q| {
358 predicate.as_ref().is_none_or(|p| *p == q.predicate)
359 && graph_name.as_ref().is_none_or(|g| *g == q.graph_name)
360 }))
361 } else if let Some(predicate) = predicate {
362 Box::new(
363 self.quads_for_predicate(predicate)
364 .filter(move |q| graph_name.as_ref().is_none_or(|g| *g == q.graph_name)),
365 )
366 } else if let Some(graph_name) = graph_name {
367 Box::new(self.quads_for_graph_name(graph_name))
368 } else {
369 Box::new(self.iter())
370 };
371 iter
372 }
373
374 pub fn contains<'a>(&self, quad: impl Into<QuadRef<'a>>) -> bool {
376 if let Some(q) = self.encoded_quad(quad.into()) {
377 self.spog.contains(&q)
378 } else {
379 false
380 }
381 }
382
383 pub fn len(&self) -> usize {
385 self.gspo.len()
386 }
387
388 pub fn is_empty(&self) -> bool {
390 self.gspo.is_empty()
391 }
392
393 pub fn insert<'a>(&mut self, quad: impl Into<QuadRef<'a>>) -> bool {
395 let quad = self.encode_quad(quad.into());
396 self.insert_encoded(quad)
397 }
398
399 fn insert_encoded(
400 &mut self,
401 quad: (
402 InternedNamedOrBlankNode,
403 InternedNamedNode,
404 InternedTerm,
405 InternedGraphName,
406 ),
407 ) -> bool {
408 let (s, p, o, g) = quad;
409 self.gspo.insert((g, s, p, o.clone()));
410 self.gpos.insert((g, p, o.clone(), s));
411 self.gosp.insert((g, o.clone(), s, p));
412 self.spog.insert((s, p, o.clone(), g));
413 self.posg.insert((p, o.clone(), s, g));
414 self.ospg.insert((o, s, p, g))
415 }
416
417 pub fn remove<'a>(&mut self, quad: impl Into<QuadRef<'a>>) -> bool {
419 if let Some(quad) = self.encoded_quad(quad.into()) {
420 self.remove_encoded(quad)
421 } else {
422 false
423 }
424 }
425
426 fn remove_encoded(
427 &mut self,
428 quad: (
429 InternedNamedOrBlankNode,
430 InternedNamedNode,
431 InternedTerm,
432 InternedGraphName,
433 ),
434 ) -> bool {
435 let (s, p, o, g) = quad;
436 self.gspo.remove(&(g, s, p, o.clone()));
437 self.gpos.remove(&(g, p, o.clone(), s));
438 self.gosp.remove(&(g, o.clone(), s, p));
439 self.spog.remove(&(s, p, o.clone(), g));
440 self.posg.remove(&(p, o.clone(), s, g));
441 self.ospg.remove(&(o, s, p, g))
442 }
443
444 pub fn clear(&mut self) {
446 self.gspo.clear();
447 self.gpos.clear();
448 self.gosp.clear();
449 self.spog.clear();
450 self.posg.clear();
451 self.ospg.clear();
452 }
453
454 fn encode_quad(
455 &mut self,
456 quad: QuadRef<'_>,
457 ) -> (
458 InternedNamedOrBlankNode,
459 InternedNamedNode,
460 InternedTerm,
461 InternedGraphName,
462 ) {
463 (
464 InternedNamedOrBlankNode::encoded_into(quad.subject, &mut self.interner),
465 InternedNamedNode::encoded_into(quad.predicate, &mut self.interner),
466 InternedTerm::encoded_into(quad.object, &mut self.interner),
467 InternedGraphName::encoded_into(quad.graph_name, &mut self.interner),
468 )
469 }
470
471 fn encoded_quad(
472 &self,
473 quad: QuadRef<'_>,
474 ) -> Option<(
475 InternedNamedOrBlankNode,
476 InternedNamedNode,
477 InternedTerm,
478 InternedGraphName,
479 )> {
480 Some((
481 self.encoded_named_or_blank_node(quad.subject)?,
482 self.encoded_named_node(quad.predicate)?,
483 self.encoded_term(quad.object)?,
484 self.encoded_graph_name(quad.graph_name)?,
485 ))
486 }
487
488 pub(super) fn encoded_named_node<'a>(
489 &self,
490 node: impl Into<NamedNodeRef<'a>>,
491 ) -> Option<InternedNamedNode> {
492 InternedNamedNode::encoded_from(node.into(), &self.interner)
493 }
494
495 pub(super) fn encoded_named_or_blank_node<'a>(
496 &self,
497 node: impl Into<NamedOrBlankNodeRef<'a>>,
498 ) -> Option<InternedNamedOrBlankNode> {
499 InternedNamedOrBlankNode::encoded_from(node.into(), &self.interner)
500 }
501
502 pub(super) fn encoded_term<'a>(&self, term: impl Into<TermRef<'a>>) -> Option<InternedTerm> {
503 InternedTerm::encoded_from(term.into(), &self.interner)
504 }
505
506 pub(super) fn encoded_graph_name<'a>(
507 &self,
508 graph_name: impl Into<GraphNameRef<'a>>,
509 ) -> Option<InternedGraphName> {
510 InternedGraphName::encoded_from(graph_name.into(), &self.interner)
511 }
512
513 fn decode_spog(
514 &self,
515 quad: (
516 &InternedNamedOrBlankNode,
517 &InternedNamedNode,
518 &InternedTerm,
519 &InternedGraphName,
520 ),
521 ) -> QuadRef<'_> {
522 QuadRef {
523 subject: quad.0.decode_from(&self.interner),
524 predicate: quad.1.decode_from(&self.interner),
525 object: quad.2.decode_from(&self.interner),
526 graph_name: quad.3.decode_from(&self.interner),
527 }
528 }
529
530 fn decode_spo(
531 &self,
532 triple: (&InternedNamedOrBlankNode, &InternedNamedNode, &InternedTerm),
533 ) -> TripleRef<'_> {
534 TripleRef {
535 subject: triple.0.decode_from(&self.interner),
536 predicate: triple.1.decode_from(&self.interner),
537 object: triple.2.decode_from(&self.interner),
538 }
539 }
540
541 pub fn canonicalize(&mut self, algorithm: CanonicalizationAlgorithm) {
580 let bnode_mapping = self.canonicalize_interned_blank_nodes(algorithm);
581 let new_quads = self.map_blank_nodes(&bnode_mapping);
582 self.clear();
583 for quad in new_quads {
584 self.insert_encoded(quad);
585 }
586 }
587
588 pub fn canonicalize_blank_nodes(
593 &self,
594 algorithm: CanonicalizationAlgorithm,
595 ) -> HashMap<BlankNodeRef<'_>, BlankNode> {
596 self.canonicalize_interned_blank_nodes(algorithm)
597 .into_iter()
598 .map(|(from, to)| (from.decode_from(&self.interner), to))
599 .collect()
600 }
601
602 fn canonicalize_interned_blank_nodes(
603 &self,
604 algorithm: CanonicalizationAlgorithm,
605 ) -> HashMap<InternedBlankNode, BlankNode> {
606 let hash_algorithm = match algorithm {
607 CanonicalizationAlgorithm::Unstable => None,
608 #[cfg(feature = "rdfc-10")]
609 CanonicalizationAlgorithm::Rdfc10 { hash_algorithm } => Some(hash_algorithm),
610 };
611 let mut canonicalization_state = CanonicalizationState {
614 blank_node_to_quads_map: QuadsPerBlankNode::new(),
615 hash_to_blank_nodes_map: BTreeMap::new(),
616 canonical_issuer: IdentifierIssuer::new("c14n"),
617 };
618 for quad in &self.spog {
620 if let InternedNamedOrBlankNode::BlankNode(bnode) = quad.0 {
621 Self::add_quad_to_blank_node_to_quads_map_for_blank_node(
622 bnode,
623 quad,
624 &mut canonicalization_state.blank_node_to_quads_map,
625 );
626 }
627 if let InternedTerm::BlankNode(bnode) = &quad.2 {
628 Self::add_quad_to_blank_node_to_quads_map_for_blank_node(
629 *bnode,
630 quad,
631 &mut canonicalization_state.blank_node_to_quads_map,
632 );
633 }
634 #[cfg(feature = "rdf-12")]
635 if let InternedTerm::Triple(t) = &quad.2 {
636 Self::add_quad_to_blank_node_to_quads_map_based_on_triple(
637 t,
638 quad,
639 &mut canonicalization_state.blank_node_to_quads_map,
640 );
641 }
642 if let InternedGraphName::BlankNode(bnode) = &quad.3 {
643 Self::add_quad_to_blank_node_to_quads_map_for_blank_node(
644 *bnode,
645 quad,
646 &mut canonicalization_state.blank_node_to_quads_map,
647 );
648 }
649 }
650 for n in canonicalization_state.blank_node_to_quads_map.keys() {
652 let hash = self.hash_first_degree_quads(&canonicalization_state, *n, hash_algorithm);
654 canonicalization_state
656 .hash_to_blank_nodes_map
657 .entry(hash)
658 .or_default()
659 .push(*n);
660 }
661 canonicalization_state.hash_to_blank_nodes_map = canonicalization_state
663 .hash_to_blank_nodes_map
664 .into_iter()
665 .filter(|(_, identifier_list)| {
666 match identifier_list.len() {
667 0 => unreachable!(),
668 2.. => true,
670 1 => {
671 Self::issue_identifier(
673 &mut canonicalization_state.canonical_issuer,
674 identifier_list[0],
675 );
676 false
678 }
679 }
680 })
681 .collect::<BTreeMap<_, _>>();
682 for (_, identifier_list) in take(&mut canonicalization_state.hash_to_blank_nodes_map) {
684 let mut hash_path_list = Vec::new();
686 for n in identifier_list {
688 if canonicalization_state
690 .canonical_issuer
691 .issued_identifier_map
692 .contains_key(&n)
693 {
694 continue;
695 }
696 let mut temporary_issuer = IdentifierIssuer::new("b");
698 Self::issue_identifier(&mut temporary_issuer, n);
700 hash_path_list.push(self.hash_n_degree_quads(
702 &canonicalization_state,
703 n,
704 &temporary_issuer,
705 hash_algorithm,
706 ))
707 }
708 hash_path_list.sort_unstable_by(|(_, hl), (_, hr)| hl.cmp(hr));
710 for (result_identifier_issuer, _) in hash_path_list {
711 for existing_identifier in result_identifier_issuer.issued_identifier_order {
713 Self::issue_identifier(
714 &mut canonicalization_state.canonical_issuer,
715 existing_identifier,
716 );
717 }
718 }
719 }
720 canonicalization_state
722 .canonical_issuer
723 .issued_identifier_map
724 }
725
726 #[cfg(feature = "rdf-12")]
727 fn add_quad_to_blank_node_to_quads_map_based_on_triple<'a>(
728 triple: &InternedTriple,
729 quad: &'a (
730 InternedNamedOrBlankNode,
731 InternedNamedNode,
732 InternedTerm,
733 InternedGraphName,
734 ),
735 blank_node_to_quads_map: &mut QuadsPerBlankNode<'a>,
736 ) {
737 if let InternedNamedOrBlankNode::BlankNode(bnode) = triple.subject {
738 Self::add_quad_to_blank_node_to_quads_map_for_blank_node(
739 bnode,
740 quad,
741 blank_node_to_quads_map,
742 );
743 }
744 if let InternedTerm::BlankNode(bnode) = &triple.object {
745 Self::add_quad_to_blank_node_to_quads_map_for_blank_node(
746 *bnode,
747 quad,
748 blank_node_to_quads_map,
749 );
750 } else if let InternedTerm::Triple(t) = &triple.object {
751 Self::add_quad_to_blank_node_to_quads_map_based_on_triple(
752 t,
753 quad,
754 blank_node_to_quads_map,
755 );
756 }
757 }
758
759 fn add_quad_to_blank_node_to_quads_map_for_blank_node<'a>(
760 bnode: InternedBlankNode,
761 quad: &'a (
762 InternedNamedOrBlankNode,
763 InternedNamedNode,
764 InternedTerm,
765 InternedGraphName,
766 ),
767 blank_node_to_quads_map: &mut QuadsPerBlankNode<'a>,
768 ) {
769 let entry = blank_node_to_quads_map.entry(bnode).or_default();
770 if !entry.ends_with(&[quad]) {
771 entry.push(quad);
772 }
773 }
774
775 fn issue_identifier(issuer: &mut IdentifierIssuer, blank_node: InternedBlankNode) -> BlankNode {
777 match issuer.issued_identifier_map.entry(blank_node) {
778 Entry::Occupied(entry) => entry.get().clone(),
780 Entry::Vacant(entry) => {
781 let issued_identifier = BlankNode::new_unchecked(format!(
783 "{}{}",
784 issuer.identifier_prefix, issuer.identifier_counter
785 ));
786 entry.insert(issued_identifier.clone());
788 issuer.issued_identifier_order.push(blank_node);
789 issuer.identifier_counter += 1;
791 issued_identifier
793 }
794 }
795 }
796
797 fn hash_first_degree_quads(
799 &self,
800 canonicalization_state: &CanonicalizationState<'_>,
801 reference_blank_node_identifier: InternedBlankNode,
802 hash_algorithm: Option<CanonicalizationHashAlgorithm>,
803 ) -> String {
804 let mut nquads = Vec::new();
806 let quads =
808 &canonicalization_state.blank_node_to_quads_map[&reference_blank_node_identifier];
809 for (subject, predicate, object, graph_name) in quads {
811 let subject = self.hash_first_degree_quads_decode_named_or_blank_node(
813 subject,
814 &reference_blank_node_identifier,
815 );
816 let predicate = predicate.decode_from(&self.interner);
817 let object =
818 self.hash_first_degree_quads_decode_term(object, &reference_blank_node_identifier);
819 let graph_name = self.hash_first_degree_quads_decode_graph_name(
820 graph_name,
821 &reference_blank_node_identifier,
822 );
823 nquads.push(if graph_name.is_default_graph() {
824 format!("{subject} {predicate} {object} .\n")
825 } else {
826 format!("{subject} {predicate} {object} {graph_name} .\n")
827 });
828 }
829 nquads.sort();
831 Self::hash_function(&nquads.join(""), hash_algorithm)
833 }
834
835 fn hash_first_degree_quads_decode_named_or_blank_node(
836 &self,
837 term: &InternedNamedOrBlankNode,
838 reference_blank_node_identifier: &InternedBlankNode,
839 ) -> NamedOrBlankNodeRef<'_> {
840 match term {
841 InternedNamedOrBlankNode::NamedNode(t) => t.decode_from(&self.interner).into(),
842 InternedNamedOrBlankNode::BlankNode(t) => {
843 BlankNodeRef::new_unchecked(if t == reference_blank_node_identifier {
844 "a"
845 } else {
846 "z"
847 })
848 .into()
849 }
850 }
851 }
852
853 fn hash_first_degree_quads_decode_term(
854 &self,
855 term: &InternedTerm,
856 reference_blank_node_identifier: &InternedBlankNode,
857 ) -> Term {
858 match term {
859 InternedTerm::NamedNode(t) => t.decode_from(&self.interner).into(),
860 InternedTerm::BlankNode(t) => {
861 BlankNodeRef::new_unchecked(if t == reference_blank_node_identifier {
862 "a"
863 } else {
864 "z"
865 })
866 .into()
867 }
868 InternedTerm::Literal(t) => t.decode_from(&self.interner).into(),
869 #[cfg(feature = "rdf-12")]
870 InternedTerm::Triple(t) => Triple::new(
871 self.hash_first_degree_quads_decode_named_or_blank_node(
872 &t.subject,
873 reference_blank_node_identifier,
874 ),
875 t.predicate.decode_from(&self.interner),
876 self.hash_first_degree_quads_decode_term(
877 &t.object,
878 reference_blank_node_identifier,
879 ),
880 )
881 .into(),
882 }
883 }
884
885 fn hash_first_degree_quads_decode_graph_name(
886 &self,
887 term: &InternedGraphName,
888 reference_blank_node_identifier: &InternedBlankNode,
889 ) -> GraphNameRef<'_> {
890 match term {
891 InternedGraphName::NamedNode(t) => t.decode_from(&self.interner).into(),
892 InternedGraphName::BlankNode(t) => {
893 BlankNodeRef::new_unchecked(if t == reference_blank_node_identifier {
894 "a"
895 } else {
896 "z"
897 })
898 .into()
899 }
900 InternedGraphName::DefaultGraph => GraphNameRef::DefaultGraph,
901 }
902 }
903
904 fn hash_related_blank_node(
906 &self,
907 canonicalization_state: &CanonicalizationState<'_>,
908 related: InternedBlankNode,
909 quad: &(
910 InternedNamedOrBlankNode,
911 InternedNamedNode,
912 InternedTerm,
913 InternedGraphName,
914 ),
915 issuer: &IdentifierIssuer,
916 position: &str,
917 hash_algorithm: Option<CanonicalizationHashAlgorithm>,
918 ) -> String {
919 let mut input = position.to_owned();
921 if position != "g" {
923 input.push('<');
924 input.push_str(quad.1.decode_from(&self.interner).as_str());
925 input.push('>');
926 }
927 if let Some(id) = canonicalization_state
929 .canonical_issuer
930 .issued_identifier_map
931 .get(&related)
932 .or_else(|| issuer.issued_identifier_map.get(&related))
933 {
934 input.push_str("_:");
935 input.push_str(id.as_str());
936 } else {
937 input.push_str(&self.hash_first_degree_quads(
939 canonicalization_state,
940 related,
941 hash_algorithm,
942 ));
943 }
944 Self::hash_function(&input, hash_algorithm)
946 }
947
948 fn hash_n_degree_quads(
950 &self,
951 canonicalization_state: &CanonicalizationState<'_>,
952 identifier: InternedBlankNode,
953 issuer: &IdentifierIssuer,
954 hash_algorithm: Option<CanonicalizationHashAlgorithm>,
955 ) -> (IdentifierIssuer, String) {
956 let mut issuer = issuer.clone();
957 let mut h_n = BTreeMap::<_, HashSet<_>>::new();
959 let quads = &canonicalization_state.blank_node_to_quads_map[&identifier];
961 for quad in quads {
963 if let InternedNamedOrBlankNode::BlankNode(component) = quad.0 {
965 self.hash_related_blank_node_on_possible_component(
966 canonicalization_state,
967 component,
968 identifier,
969 quad,
970 &issuer,
971 "s",
972 &mut h_n,
973 hash_algorithm,
974 );
975 }
976 if let InternedTerm::BlankNode(component) = quad.2 {
977 self.hash_related_blank_node_on_possible_component(
978 canonicalization_state,
979 component,
980 identifier,
981 quad,
982 &issuer,
983 "o",
984 &mut h_n,
985 hash_algorithm,
986 );
987 }
988 #[cfg(feature = "rdf-12")]
989 if let InternedTerm::Triple(t) = &quad.2 {
990 self.hash_related_blank_node_on_possible_triple(
991 canonicalization_state,
992 t,
993 identifier,
994 quad,
995 &issuer,
996 &mut h_n,
997 hash_algorithm,
998 );
999 }
1000 if let InternedGraphName::BlankNode(component) = quad.3 {
1001 self.hash_related_blank_node_on_possible_component(
1002 canonicalization_state,
1003 component,
1004 identifier,
1005 quad,
1006 &issuer,
1007 "g",
1008 &mut h_n,
1009 hash_algorithm,
1010 );
1011 }
1012 }
1013 let mut data_to_hash = String::new();
1015 for (related_hash, blank_node_list) in h_n {
1017 data_to_hash.push_str(&related_hash);
1019 let mut chosen_path = String::new();
1021 let mut chosen_issuer = IdentifierIssuer::new("");
1023 'perm: for p in generate_permutations(blank_node_list) {
1025 let mut issuer_copy = issuer.clone();
1027 let mut path = String::new();
1029 let mut recursion_list = Vec::new();
1031 for related in p {
1033 if let Some(id) = canonicalization_state
1035 .canonical_issuer
1036 .issued_identifier_map
1037 .get(&related)
1038 {
1039 path.push_str("_:");
1040 path.push_str(id.as_str());
1041 } else {
1042 if !issuer_copy.issued_identifier_map.contains_key(&related) {
1045 recursion_list.push(related);
1046 }
1047 let id = Self::issue_identifier(&mut issuer_copy, related);
1049 path.push_str("_:");
1050 path.push_str(id.as_str());
1051 }
1052 if !chosen_path.is_empty()
1054 && path.len() >= chosen_path.len()
1055 && path > chosen_path
1056 {
1057 continue 'perm;
1058 }
1059 }
1060 for related in recursion_list {
1062 let (result_identifier_issuer, result_hash) = self.hash_n_degree_quads(
1064 canonicalization_state,
1065 related,
1066 &issuer_copy,
1067 hash_algorithm,
1068 );
1069 let id = Self::issue_identifier(&mut issuer_copy, related);
1071 path.push_str("_:");
1072 path.push_str(id.as_str());
1073 path.push('<');
1075 path.push_str(&result_hash);
1076 path.push('>');
1077 issuer_copy = result_identifier_issuer;
1079 if !chosen_path.is_empty()
1081 && path.len() >= chosen_path.len()
1082 && path > chosen_path
1083 {
1084 continue 'perm;
1085 }
1086 }
1087 if chosen_path.is_empty() || path < chosen_path {
1089 chosen_path = path;
1090 chosen_issuer = issuer_copy;
1091 }
1092 }
1093 data_to_hash.push_str(&chosen_path);
1095 issuer = chosen_issuer;
1097 }
1098 (issuer, Self::hash_function(&data_to_hash, hash_algorithm))
1100 }
1101
1102 #[cfg(feature = "rdf-12")]
1103 fn hash_related_blank_node_on_possible_triple(
1104 &self,
1105 canonicalization_state: &CanonicalizationState<'_>,
1106 triple: &InternedTriple,
1107 identifier: InternedBlankNode,
1108 quad: &(
1109 InternedNamedOrBlankNode,
1110 InternedNamedNode,
1111 InternedTerm,
1112 InternedGraphName,
1113 ),
1114 issuer: &IdentifierIssuer,
1115 h_n: &mut BTreeMap<String, HashSet<InternedBlankNode>>,
1116 hash_algorithm: Option<CanonicalizationHashAlgorithm>,
1117 ) {
1118 if let InternedNamedOrBlankNode::BlankNode(component) = triple.subject {
1119 self.hash_related_blank_node_on_possible_component(
1120 canonicalization_state,
1121 component,
1122 identifier,
1123 quad,
1124 issuer,
1125 "os",
1126 h_n,
1127 hash_algorithm,
1128 );
1129 }
1130 if let InternedTerm::BlankNode(component) = &triple.object {
1131 self.hash_related_blank_node_on_possible_component(
1132 canonicalization_state,
1133 *component,
1134 identifier,
1135 quad,
1136 issuer,
1137 "oo",
1138 h_n,
1139 hash_algorithm,
1140 );
1141 }
1142 }
1143
1144 fn hash_related_blank_node_on_possible_component(
1145 &self,
1146 canonicalization_state: &CanonicalizationState<'_>,
1147 component: InternedBlankNode,
1148 identifier: InternedBlankNode,
1149 quad: &(
1150 InternedNamedOrBlankNode,
1151 InternedNamedNode,
1152 InternedTerm,
1153 InternedGraphName,
1154 ),
1155 issuer: &IdentifierIssuer,
1156 position: &str,
1157 h_n: &mut BTreeMap<String, HashSet<InternedBlankNode>>,
1158 hash_algorithm: Option<CanonicalizationHashAlgorithm>,
1159 ) {
1160 if component != identifier {
1161 let hash = self.hash_related_blank_node(
1163 canonicalization_state,
1164 component,
1165 quad,
1166 issuer,
1167 position,
1168 hash_algorithm,
1169 );
1170 h_n.entry(hash).or_default().insert(component);
1172 }
1173 }
1174
1175 fn hash_function(input: &str, hash_algorithm: Option<CanonicalizationHashAlgorithm>) -> String {
1176 match hash_algorithm {
1177 #[cfg(feature = "rdfc-10")]
1178 Some(CanonicalizationHashAlgorithm::Sha256) => {
1179 hex::encode(Sha256::new().chain_update(input).finalize())
1180 }
1181 #[cfg(feature = "rdfc-10")]
1182 Some(CanonicalizationHashAlgorithm::Sha384) => {
1183 hex::encode(Sha384::new().chain_update(input).finalize())
1184 }
1185 None => {
1186 let mut hasher = DefaultHasher::new();
1187 input.hash(&mut hasher);
1188 hasher.finish().to_string()
1189 }
1190 }
1191 }
1192
1193 #[expect(clippy::needless_collect)]
1194 fn map_blank_nodes(
1195 &mut self,
1196 bnode_mapping: &HashMap<InternedBlankNode, BlankNode>,
1197 ) -> Vec<(
1198 InternedNamedOrBlankNode,
1199 InternedNamedNode,
1200 InternedTerm,
1201 InternedGraphName,
1202 )> {
1203 let old_quads: Vec<_> = self.spog.iter().cloned().collect();
1204 old_quads
1205 .into_iter()
1206 .map(|(s, p, o, g)| {
1207 (
1208 match s {
1209 InternedNamedOrBlankNode::NamedNode(_) => s,
1210 InternedNamedOrBlankNode::BlankNode(bnode) => {
1211 InternedNamedOrBlankNode::BlankNode(InternedBlankNode::encoded_into(
1212 bnode_mapping[&bnode].as_ref(),
1213 &mut self.interner,
1214 ))
1215 }
1216 },
1217 p,
1218 match o {
1219 InternedTerm::NamedNode(_) | InternedTerm::Literal(_) => o,
1220 InternedTerm::BlankNode(bnode) => {
1221 InternedTerm::BlankNode(InternedBlankNode::encoded_into(
1222 bnode_mapping[&bnode].as_ref(),
1223 &mut self.interner,
1224 ))
1225 }
1226 #[cfg(feature = "rdf-12")]
1227 InternedTerm::Triple(triple) => {
1228 InternedTerm::Triple(Box::new(InternedTriple::encoded_into(
1229 self.map_triple_blank_nodes(&triple, bnode_mapping).as_ref(),
1230 &mut self.interner,
1231 )))
1232 }
1233 },
1234 match g {
1235 InternedGraphName::NamedNode(_) | InternedGraphName::DefaultGraph => g,
1236 InternedGraphName::BlankNode(bnode) => {
1237 InternedGraphName::BlankNode(InternedBlankNode::encoded_into(
1238 bnode_mapping[&bnode].as_ref(),
1239 &mut self.interner,
1240 ))
1241 }
1242 },
1243 )
1244 })
1245 .collect()
1246 }
1247
1248 #[cfg(feature = "rdf-12")]
1249 fn map_triple_blank_nodes(
1250 &mut self,
1251 triple: &InternedTriple,
1252 bnode_mapping: &HashMap<InternedBlankNode, BlankNode>,
1253 ) -> Triple {
1254 Triple {
1255 subject: if let InternedNamedOrBlankNode::BlankNode(bnode) = &triple.subject {
1256 bnode_mapping[bnode].clone().into()
1257 } else {
1258 triple.subject.decode_from(&self.interner).into_owned()
1259 },
1260 predicate: triple.predicate.decode_from(&self.interner).into_owned(),
1261 object: if let InternedTerm::BlankNode(bnode) = &triple.object {
1262 bnode_mapping[bnode].clone().into()
1263 } else if let InternedTerm::Triple(t) = &triple.object {
1264 self.map_triple_blank_nodes(t, bnode_mapping).into()
1265 } else {
1266 triple.object.decode_from(&self.interner).into_owned()
1267 },
1268 }
1269 }
1270}
1271
1272impl PartialEq for Dataset {
1273 fn eq(&self, other: &Self) -> bool {
1274 if self.len() != other.len() {
1275 return false;
1276 }
1277 for q in self {
1278 if !other.contains(q) {
1279 return false;
1280 }
1281 }
1282 true
1283 }
1284}
1285
1286impl Eq for Dataset {}
1287
1288impl<'a> IntoIterator for &'a Dataset {
1289 type Item = QuadRef<'a>;
1290 type IntoIter = Iter<'a>;
1291
1292 fn into_iter(self) -> Self::IntoIter {
1293 self.iter()
1294 }
1295}
1296
1297impl FromIterator<Quad> for Dataset {
1298 fn from_iter<I: IntoIterator<Item = Quad>>(iter: I) -> Self {
1299 let mut g = Self::new();
1300 g.extend(iter);
1301 g
1302 }
1303}
1304
1305impl<'a, T: Into<QuadRef<'a>>> FromIterator<T> for Dataset {
1306 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
1307 let mut g = Self::new();
1308 g.extend(iter);
1309 g
1310 }
1311}
1312
1313impl Extend<Quad> for Dataset {
1314 fn extend<I: IntoIterator<Item = Quad>>(&mut self, iter: I) {
1315 for t in iter {
1316 self.insert(&t);
1317 }
1318 }
1319}
1320
1321impl<'a, T: Into<QuadRef<'a>>> Extend<T> for Dataset {
1322 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
1323 for t in iter {
1324 self.insert(t);
1325 }
1326 }
1327}
1328
1329impl fmt::Display for Dataset {
1330 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1331 for t in self {
1332 writeln!(f, "{t} .")?;
1333 }
1334 Ok(())
1335 }
1336}
1337
1338#[derive(Clone, Debug)]
1355pub struct GraphView<'a> {
1356 dataset: &'a Dataset,
1357 graph_name: InternedGraphName,
1358}
1359
1360impl<'a> GraphView<'a> {
1361 pub fn iter(&self) -> GraphViewIter<'a> {
1363 let iter = self.dataset.gspo.range(
1364 &(
1365 self.graph_name,
1366 InternedNamedOrBlankNode::first(),
1367 InternedNamedNode::first(),
1368 InternedTerm::first(),
1369 )
1370 ..&(
1371 self.graph_name.next(),
1372 InternedNamedOrBlankNode::first(),
1373 InternedNamedNode::first(),
1374 InternedTerm::first(),
1375 ),
1376 );
1377 GraphViewIter {
1378 dataset: self.dataset,
1379 inner: iter,
1380 }
1381 }
1382
1383 pub fn triples_for_subject<'b>(
1384 &self,
1385 subject: impl Into<NamedOrBlankNodeRef<'b>>,
1386 ) -> impl Iterator<Item = TripleRef<'a>> + 'a {
1387 self.triples_for_interned_subject(self.dataset.encoded_named_or_blank_node(subject))
1388 }
1389
1390 pub(super) fn triples_for_interned_subject(
1391 &self,
1392 subject: Option<InternedNamedOrBlankNode>,
1393 ) -> impl Iterator<Item = TripleRef<'a>> + use<'a> {
1394 let subject = subject.unwrap_or_else(InternedNamedOrBlankNode::impossible);
1395 let ds = self.dataset;
1396 self.dataset
1397 .gspo
1398 .range(
1399 &(
1400 self.graph_name,
1401 subject,
1402 InternedNamedNode::first(),
1403 InternedTerm::first(),
1404 )
1405 ..&(
1406 self.graph_name,
1407 subject.next(),
1408 InternedNamedNode::first(),
1409 InternedTerm::first(),
1410 ),
1411 )
1412 .map(move |q| {
1413 let (_, s, p, o) = q;
1414 ds.decode_spo((s, p, o))
1415 })
1416 }
1417
1418 pub fn objects_for_subject_predicate<'b>(
1419 &self,
1420 subject: impl Into<NamedOrBlankNodeRef<'b>>,
1421 predicate: impl Into<NamedNodeRef<'b>>,
1422 ) -> impl Iterator<Item = TermRef<'a>> + 'a {
1423 self.objects_for_interned_subject_predicate(
1424 self.dataset.encoded_named_or_blank_node(subject),
1425 self.dataset.encoded_named_node(predicate),
1426 )
1427 }
1428
1429 pub(super) fn objects_for_interned_subject_predicate(
1430 &self,
1431 subject: Option<InternedNamedOrBlankNode>,
1432 predicate: Option<InternedNamedNode>,
1433 ) -> impl Iterator<Item = TermRef<'a>> + use<'a> {
1434 let subject = subject.unwrap_or_else(InternedNamedOrBlankNode::impossible);
1435 let predicate = predicate.unwrap_or_else(InternedNamedNode::impossible);
1436 let ds = self.dataset;
1437 self.dataset
1438 .gspo
1439 .range(
1440 &(self.graph_name, subject, predicate, InternedTerm::first())
1441 ..&(
1442 self.graph_name,
1443 subject,
1444 predicate.next(),
1445 InternedTerm::first(),
1446 ),
1447 )
1448 .map(move |q| q.3.decode_from(&ds.interner))
1449 }
1450
1451 pub fn object_for_subject_predicate<'b>(
1452 &self,
1453 subject: impl Into<NamedOrBlankNodeRef<'b>>,
1454 predicate: impl Into<NamedNodeRef<'b>>,
1455 ) -> Option<TermRef<'a>> {
1456 self.objects_for_subject_predicate(subject, predicate)
1457 .next()
1458 }
1459
1460 pub fn predicates_for_subject_object<'b>(
1461 &self,
1462 subject: impl Into<NamedOrBlankNodeRef<'b>>,
1463 object: impl Into<TermRef<'b>>,
1464 ) -> impl Iterator<Item = NamedNodeRef<'a>> + 'a {
1465 self.predicates_for_interned_subject_object(
1466 self.dataset.encoded_named_or_blank_node(subject),
1467 self.dataset.encoded_term(object),
1468 )
1469 }
1470
1471 pub(super) fn predicates_for_interned_subject_object(
1472 &self,
1473 subject: Option<InternedNamedOrBlankNode>,
1474 object: Option<InternedTerm>,
1475 ) -> impl Iterator<Item = NamedNodeRef<'a>> + use<'a> {
1476 let subject = subject.unwrap_or_else(InternedNamedOrBlankNode::impossible);
1477 let object = object.unwrap_or_else(InternedTerm::impossible);
1478 let ds = self.dataset;
1479 self.dataset
1480 .gosp
1481 .range(
1482 &(
1483 self.graph_name,
1484 object.clone(),
1485 subject,
1486 InternedNamedNode::first(),
1487 )
1488 ..&(
1489 self.graph_name,
1490 object,
1491 subject.next(),
1492 InternedNamedNode::first(),
1493 ),
1494 )
1495 .map(move |q| q.3.decode_from(&ds.interner))
1496 }
1497
1498 pub fn triples_for_predicate<'b>(
1499 &self,
1500 predicate: impl Into<NamedNodeRef<'b>>,
1501 ) -> impl Iterator<Item = TripleRef<'a>> + 'a {
1502 self.triples_for_interned_predicate(self.dataset.encoded_named_node(predicate))
1503 }
1504
1505 pub(super) fn triples_for_interned_predicate(
1506 &self,
1507 predicate: Option<InternedNamedNode>,
1508 ) -> impl Iterator<Item = TripleRef<'a>> + use<'a> {
1509 let predicate = predicate.unwrap_or_else(InternedNamedNode::impossible);
1510 let ds = self.dataset;
1511 self.dataset
1512 .gpos
1513 .range(
1514 &(
1515 self.graph_name,
1516 predicate,
1517 InternedTerm::first(),
1518 InternedNamedOrBlankNode::first(),
1519 )
1520 ..&(
1521 self.graph_name,
1522 predicate.next(),
1523 InternedTerm::first(),
1524 InternedNamedOrBlankNode::first(),
1525 ),
1526 )
1527 .map(move |(_, p, o, s)| ds.decode_spo((s, p, o)))
1528 }
1529
1530 pub fn subjects_for_predicate_object<'b>(
1531 &self,
1532 predicate: impl Into<NamedNodeRef<'b>>,
1533 object: impl Into<TermRef<'b>>,
1534 ) -> impl Iterator<Item = NamedOrBlankNodeRef<'a>> + 'a {
1535 self.subjects_for_interned_predicate_object(
1536 self.dataset.encoded_named_node(predicate),
1537 self.dataset.encoded_term(object),
1538 )
1539 }
1540
1541 pub(super) fn subjects_for_interned_predicate_object(
1542 &self,
1543 predicate: Option<InternedNamedNode>,
1544 object: Option<InternedTerm>,
1545 ) -> impl Iterator<Item = NamedOrBlankNodeRef<'a>> + use<'a> {
1546 let predicate = predicate.unwrap_or_else(InternedNamedNode::impossible);
1547 let object = object.unwrap_or_else(InternedTerm::impossible);
1548 let ds = self.dataset;
1549 self.dataset
1550 .gpos
1551 .range(
1552 &(
1553 self.graph_name,
1554 predicate,
1555 object.clone(),
1556 InternedNamedOrBlankNode::first(),
1557 )
1558 ..&(
1559 self.graph_name,
1560 predicate,
1561 object.next(),
1562 InternedNamedOrBlankNode::first(),
1563 ),
1564 )
1565 .map(move |q| q.3.decode_from(&ds.interner))
1566 }
1567
1568 pub fn subject_for_predicate_object<'b>(
1569 &self,
1570 predicate: impl Into<NamedNodeRef<'b>>,
1571 object: impl Into<TermRef<'b>>,
1572 ) -> Option<NamedOrBlankNodeRef<'a>> {
1573 self.subjects_for_predicate_object(predicate, object).next()
1574 }
1575
1576 pub fn triples_for_object<'b>(
1577 &self,
1578 object: impl Into<TermRef<'b>>,
1579 ) -> impl Iterator<Item = TripleRef<'a>> + 'a {
1580 self.triples_for_interned_object(self.dataset.encoded_term(object))
1581 }
1582
1583 pub(super) fn triples_for_interned_object(
1584 &self,
1585 object: Option<InternedTerm>,
1586 ) -> impl Iterator<Item = TripleRef<'a>> + use<'a> {
1587 let object = object.unwrap_or_else(InternedTerm::impossible);
1588 let ds = self.dataset;
1589 self.dataset
1590 .gosp
1591 .range(
1592 &(
1593 self.graph_name,
1594 object.clone(),
1595 InternedNamedOrBlankNode::first(),
1596 InternedNamedNode::first(),
1597 )
1598 ..&(
1599 self.graph_name,
1600 object.next(),
1601 InternedNamedOrBlankNode::first(),
1602 InternedNamedNode::first(),
1603 ),
1604 )
1605 .map(move |(_, o, s, p)| ds.decode_spo((s, p, o)))
1606 }
1607
1608 pub fn triples_for_pattern(
1610 &self,
1611 subject: Option<NamedOrBlankNodeRef<'a>>,
1612 predicate: Option<NamedNodeRef<'a>>,
1613 object: Option<TermRef<'a>>,
1614 ) -> impl Iterator<Item = TripleRef<'a>> + 'a {
1615 let iter: Box<dyn Iterator<Item = _>> = match (subject, predicate, object) {
1616 (Some(subject), Some(predicate), Some(object)) => {
1617 let triple = TripleRef::new(subject, predicate, object);
1618 Box::new(self.contains(triple).then_some(triple).into_iter())
1619 }
1620 (Some(subject), Some(predicate), None) => Box::new(
1621 self.objects_for_subject_predicate(subject, predicate)
1622 .map(move |object| TripleRef::new(subject, predicate, object)),
1623 ),
1624 (Some(subject), None, Some(object)) => Box::new(
1625 self.predicates_for_subject_object(subject, object)
1626 .map(move |predicate| TripleRef::new(subject, predicate, object)),
1627 ),
1628 (Some(subject), None, None) => Box::new(self.triples_for_subject(subject)),
1629 (None, Some(predicate), Some(object)) => Box::new(
1630 self.subjects_for_predicate_object(predicate, object)
1631 .map(move |subject| TripleRef::new(subject, predicate, object)),
1632 ),
1633 (None, Some(predicate), None) => Box::new(self.triples_for_predicate(predicate)),
1634 (None, None, Some(object)) => Box::new(self.triples_for_object(object)),
1635 (None, None, None) => Box::new(self.iter()),
1636 };
1637 iter
1638 }
1639
1640 pub fn contains<'b>(&self, triple: impl Into<TripleRef<'b>>) -> bool {
1642 if let Some(triple) = self.encoded_triple(triple.into()) {
1643 self.dataset.gspo.contains(&(
1644 self.graph_name,
1645 triple.subject,
1646 triple.predicate,
1647 triple.object,
1648 ))
1649 } else {
1650 false
1651 }
1652 }
1653
1654 pub fn len(&self) -> usize {
1656 self.iter().count()
1657 }
1658
1659 pub fn is_empty(&self) -> bool {
1661 self.iter().next().is_none()
1662 }
1663
1664 fn encoded_triple(&self, triple: TripleRef<'_>) -> Option<InternedTriple> {
1665 Some(InternedTriple {
1666 subject: self.dataset.encoded_named_or_blank_node(triple.subject)?,
1667 predicate: self.dataset.encoded_named_node(triple.predicate)?,
1668 object: self.dataset.encoded_term(triple.object)?,
1669 })
1670 }
1671}
1672
1673impl<'a> IntoIterator for GraphView<'a> {
1674 type Item = TripleRef<'a>;
1675 type IntoIter = GraphViewIter<'a>;
1676
1677 fn into_iter(self) -> Self::IntoIter {
1678 self.iter()
1679 }
1680}
1681
1682impl<'a> IntoIterator for &GraphView<'a> {
1683 type Item = TripleRef<'a>;
1684 type IntoIter = GraphViewIter<'a>;
1685
1686 fn into_iter(self) -> Self::IntoIter {
1687 self.iter()
1688 }
1689}
1690
1691impl fmt::Display for GraphView<'_> {
1692 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1693 for t in self {
1694 writeln!(f, "{t} .")?;
1695 }
1696 Ok(())
1697 }
1698}
1699
1700#[derive(Debug)]
1725pub struct GraphViewMut<'a> {
1726 dataset: &'a mut Dataset,
1727 graph_name: InternedGraphName,
1728}
1729
1730impl<'a> GraphViewMut<'a> {
1731 fn read(&self) -> GraphView<'_> {
1732 GraphView {
1733 dataset: self.dataset,
1734 graph_name: self.graph_name,
1735 }
1736 }
1737
1738 pub fn insert<'b>(&mut self, triple: impl Into<TripleRef<'b>>) -> bool {
1740 let triple = self.encode_triple(triple.into());
1741 self.dataset.insert_encoded((
1742 triple.subject,
1743 triple.predicate,
1744 triple.object,
1745 self.graph_name,
1746 ))
1747 }
1748
1749 pub fn remove<'b>(&mut self, triple: impl Into<TripleRef<'b>>) -> bool {
1751 if let Some(triple) = self.read().encoded_triple(triple.into()) {
1752 self.dataset.remove_encoded((
1753 triple.subject,
1754 triple.predicate,
1755 triple.object,
1756 self.graph_name,
1757 ))
1758 } else {
1759 false
1760 }
1761 }
1762
1763 fn encode_triple(&mut self, triple: TripleRef<'_>) -> InternedTriple {
1764 InternedTriple {
1765 subject: InternedNamedOrBlankNode::encoded_into(
1766 triple.subject,
1767 &mut self.dataset.interner,
1768 ),
1769 predicate: InternedNamedNode::encoded_into(
1770 triple.predicate,
1771 &mut self.dataset.interner,
1772 ),
1773 object: InternedTerm::encoded_into(triple.object, &mut self.dataset.interner),
1774 }
1775 }
1776
1777 pub fn iter(&'a self) -> GraphViewIter<'a> {
1779 self.read().iter()
1780 }
1781
1782 pub fn triples_for_subject<'b>(
1783 &'a self,
1784 subject: impl Into<NamedOrBlankNodeRef<'b>>,
1785 ) -> impl Iterator<Item = TripleRef<'a>> + 'a {
1786 self.read()
1787 .triples_for_interned_subject(self.dataset.encoded_named_or_blank_node(subject))
1788 }
1789
1790 pub fn objects_for_subject_predicate<'b>(
1791 &'a self,
1792 subject: impl Into<NamedOrBlankNodeRef<'b>>,
1793 predicate: impl Into<NamedNodeRef<'b>>,
1794 ) -> impl Iterator<Item = TermRef<'a>> + 'a {
1795 self.read().objects_for_interned_subject_predicate(
1796 self.dataset.encoded_named_or_blank_node(subject),
1797 self.dataset.encoded_named_node(predicate),
1798 )
1799 }
1800
1801 pub fn object_for_subject_predicate<'b>(
1802 &'a self,
1803 subject: impl Into<NamedOrBlankNodeRef<'b>>,
1804 predicate: impl Into<NamedNodeRef<'b>>,
1805 ) -> Option<TermRef<'a>> {
1806 self.read().object_for_subject_predicate(subject, predicate)
1807 }
1808
1809 pub fn predicates_for_subject_object<'b>(
1810 &'a self,
1811 subject: impl Into<NamedOrBlankNodeRef<'b>>,
1812 object: impl Into<TermRef<'b>>,
1813 ) -> impl Iterator<Item = NamedNodeRef<'a>> + 'a {
1814 self.read().predicates_for_interned_subject_object(
1815 self.dataset.encoded_named_or_blank_node(subject),
1816 self.dataset.encoded_term(object),
1817 )
1818 }
1819
1820 pub fn triples_for_predicate<'b>(
1821 &'a self,
1822 predicate: impl Into<NamedNodeRef<'b>>,
1823 ) -> impl Iterator<Item = TripleRef<'a>> + 'a {
1824 self.read()
1825 .triples_for_interned_predicate(self.dataset.encoded_named_node(predicate))
1826 }
1827
1828 pub fn subjects_for_predicate_object<'b>(
1829 &'a self,
1830 predicate: impl Into<NamedNodeRef<'b>>,
1831 object: impl Into<TermRef<'b>>,
1832 ) -> impl Iterator<Item = NamedOrBlankNodeRef<'a>> + 'a {
1833 self.read().subjects_for_interned_predicate_object(
1834 self.dataset.encoded_named_node(predicate),
1835 self.dataset.encoded_term(object),
1836 )
1837 }
1838
1839 pub fn subject_for_predicate_object<'b>(
1840 &'a self,
1841 predicate: impl Into<NamedNodeRef<'b>>,
1842 object: impl Into<TermRef<'b>>,
1843 ) -> Option<NamedOrBlankNodeRef<'a>> {
1844 self.read().subject_for_predicate_object(predicate, object)
1845 }
1846
1847 pub fn triples_for_object<'b>(
1848 &'a self,
1849 object: TermRef<'b>,
1850 ) -> impl Iterator<Item = TripleRef<'a>> + 'a {
1851 self.read()
1852 .triples_for_interned_object(self.dataset.encoded_term(object))
1853 }
1854
1855 pub fn contains<'b>(&self, triple: impl Into<TripleRef<'b>>) -> bool {
1857 self.read().contains(triple)
1858 }
1859
1860 pub fn len(&self) -> usize {
1862 self.read().len()
1863 }
1864
1865 pub fn is_empty(&self) -> bool {
1867 self.read().is_empty()
1868 }
1869}
1870
1871impl Extend<Triple> for GraphViewMut<'_> {
1872 fn extend<I: IntoIterator<Item = Triple>>(&mut self, iter: I) {
1873 for t in iter {
1874 self.insert(&t);
1875 }
1876 }
1877}
1878
1879impl<'b, T: Into<TripleRef<'b>>> Extend<T> for GraphViewMut<'_> {
1880 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
1881 for t in iter {
1882 self.insert(t);
1883 }
1884 }
1885}
1886
1887impl<'a> IntoIterator for &'a GraphViewMut<'a> {
1888 type Item = TripleRef<'a>;
1889 type IntoIter = GraphViewIter<'a>;
1890
1891 fn into_iter(self) -> Self::IntoIter {
1892 self.iter()
1893 }
1894}
1895
1896impl fmt::Display for GraphViewMut<'_> {
1897 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1898 for t in self {
1899 writeln!(f, "{t}")?;
1900 }
1901 Ok(())
1902 }
1903}
1904
1905pub struct Iter<'a> {
1907 dataset: &'a Dataset,
1908 inner: std::collections::btree_set::Iter<
1909 'a,
1910 (
1911 InternedNamedOrBlankNode,
1912 InternedNamedNode,
1913 InternedTerm,
1914 InternedGraphName,
1915 ),
1916 >,
1917}
1918
1919impl<'a> Iterator for Iter<'a> {
1920 type Item = QuadRef<'a>;
1921
1922 fn next(&mut self) -> Option<Self::Item> {
1923 self.inner
1924 .next()
1925 .map(|(s, p, o, g)| self.dataset.decode_spog((s, p, o, g)))
1926 }
1927}
1928
1929pub struct GraphViewIter<'a> {
1931 dataset: &'a Dataset,
1932 inner: std::collections::btree_set::Range<
1933 'a,
1934 (
1935 InternedGraphName,
1936 InternedNamedOrBlankNode,
1937 InternedNamedNode,
1938 InternedTerm,
1939 ),
1940 >,
1941}
1942
1943impl<'a> Iterator for GraphViewIter<'a> {
1944 type Item = TripleRef<'a>;
1945
1946 fn next(&mut self) -> Option<Self::Item> {
1947 self.inner
1948 .next()
1949 .map(|(_, s, p, o)| self.dataset.decode_spo((s, p, o)))
1950 }
1951}
1952
1953type QuadsPerBlankNode<'a> = HashMap<
1954 InternedBlankNode,
1955 Vec<&'a (
1956 InternedNamedOrBlankNode,
1957 InternedNamedNode,
1958 InternedTerm,
1959 InternedGraphName,
1960 )>,
1961>;
1962
1963#[derive(Default, Debug, Clone, Copy, Eq, PartialEq, Hash)]
1967#[non_exhaustive]
1968pub enum CanonicalizationAlgorithm {
1969 #[default]
1973 Unstable,
1974 #[cfg(feature = "rdfc-10")]
1978 Rdfc10 {
1979 hash_algorithm: CanonicalizationHashAlgorithm,
1980 },
1981}
1982
1983#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
1987#[non_exhaustive]
1988pub enum CanonicalizationHashAlgorithm {
1989 #[cfg(feature = "rdfc-10")]
1990 Sha256,
1991 #[cfg(feature = "rdfc-10")]
1992 Sha384,
1993}
1994
1995struct CanonicalizationState<'a> {
1997 blank_node_to_quads_map: QuadsPerBlankNode<'a>,
1998 hash_to_blank_nodes_map: BTreeMap<String, Vec<InternedBlankNode>>,
1999 canonical_issuer: IdentifierIssuer,
2000}
2001
2002#[derive(Clone)]
2004struct IdentifierIssuer {
2005 identifier_prefix: &'static str,
2006 identifier_counter: u32,
2007 issued_identifier_map: HashMap<InternedBlankNode, BlankNode>,
2008 issued_identifier_order: Vec<InternedBlankNode>, }
2010
2011impl IdentifierIssuer {
2012 fn new(identifier_prefix: &'static str) -> Self {
2013 Self {
2014 identifier_prefix,
2015 identifier_counter: 0,
2016 issued_identifier_map: HashMap::new(),
2017 issued_identifier_order: Vec::new(),
2018 }
2019 }
2020}
2021
2022fn generate_permutations<T: Copy>(items: impl IntoIterator<Item = T>) -> Vec<Vec<T>> {
2023 let mut current_output = vec![Vec::new()];
2024 for (i, next) in items.into_iter().enumerate() {
2025 let mut new_output = Vec::with_capacity(current_output.len() * (i + 1));
2026 for mut permutation in current_output {
2027 permutation.push(next);
2028 for j in 0..=i {
2029 let mut new_permutation = permutation.clone();
2030 new_permutation.swap(i, j);
2031 new_output.push(new_permutation);
2032 }
2033 }
2034 current_output = new_output;
2035 }
2036 current_output
2037}
2038
2039#[cfg(feature = "rdfc-10")]
2040#[cfg(test)]
2041mod tests {
2042 use super::*;
2043
2044 #[test]
2045 fn test_canon() {
2046 let p = NamedNode::new_unchecked("http://example.com/#p");
2047 let q = NamedNode::new_unchecked("http://example.com/#q");
2048 let r = NamedNode::new_unchecked("http://example.com/#r");
2049
2050 let mut dataset = Dataset::new();
2051 let e0 = BlankNode::new_unchecked("e0");
2052 let e1 = BlankNode::new_unchecked("e1");
2053 let e2 = BlankNode::new_unchecked("e2");
2054 let e3 = BlankNode::new_unchecked("e3");
2055 dataset.insert(QuadRef::new(&p, &q, &e0, GraphNameRef::DefaultGraph));
2056 dataset.insert(QuadRef::new(&p, &q, &e1, GraphNameRef::DefaultGraph));
2057 dataset.insert(QuadRef::new(&e0, &p, &e2, GraphNameRef::DefaultGraph));
2058 dataset.insert(QuadRef::new(&e1, &p, &e3, GraphNameRef::DefaultGraph));
2059 dataset.insert(QuadRef::new(&e2, &r, &e3, GraphNameRef::DefaultGraph));
2060 dataset.canonicalize(CanonicalizationAlgorithm::Rdfc10 {
2061 hash_algorithm: CanonicalizationHashAlgorithm::Sha256,
2062 });
2063
2064 let mut expected = Dataset::new();
2065 let c14n0 = BlankNode::new_unchecked("c14n0");
2066 let c14n1 = BlankNode::new_unchecked("c14n1");
2067 let c14n2 = BlankNode::new_unchecked("c14n2");
2068 let c14n3 = BlankNode::new_unchecked("c14n3");
2069 expected.insert(QuadRef::new(&p, &q, &c14n2, GraphNameRef::DefaultGraph));
2070 expected.insert(QuadRef::new(&p, &q, &c14n3, GraphNameRef::DefaultGraph));
2071 expected.insert(QuadRef::new(&c14n0, &r, &c14n1, GraphNameRef::DefaultGraph));
2072 expected.insert(QuadRef::new(&c14n2, &p, &c14n1, GraphNameRef::DefaultGraph));
2073 expected.insert(QuadRef::new(&c14n3, &p, &c14n0, GraphNameRef::DefaultGraph));
2074 assert_eq!(dataset, expected);
2075 }
2076}