grdf/impl/hash_dataset/
graph.rs

1use core::{fmt, hash::Hash};
2use educe::Educe;
3use hashbrown::{Equivalent, HashMap, HashSet};
4use rdf_types::Triple;
5
6use crate::GraphView;
7
8use super::GraphPatternMatching;
9
10/// Graph implementation based on `HashMap` and `HashSet`.
11#[derive(Educe, Clone)]
12#[educe(PartialEq(bound = "S: Eq + Hash, P: Eq + Hash, O: Eq + Hash"))]
13#[educe(Eq(bound = "S: Eq + Hash, P: Eq + Hash, O: Eq + Hash"))]
14#[educe(Default)]
15pub struct HashGraph<S = rdf_types::Term, P = S, O = S> {
16	pub(crate) table: HashMap<S, HashMap<P, HashSet<O>>>,
17	len: usize,
18}
19
20impl<S, P, O> HashGraph<S, P, O> {
21	/// Create a new empty `HashGraph`.
22	pub fn new() -> Self {
23		Self::default()
24	}
25
26	/// Returns the number of triples in the graph.
27	pub fn len(&self) -> usize {
28		self.len
29	}
30
31	/// Checks if the graph is empty.
32	pub fn is_empty(&self) -> bool {
33		self.len == 0
34	}
35}
36
37impl<S: Eq + Hash, P: Eq + Hash, O: Eq + Hash> HashGraph<S, P, O> {
38	/// Create a new `HashGraph` from another graph by consuming its triples.
39	pub fn from_graph<G: crate::SizedGraph<Subject = S, Predicate = P, Object = O>>(
40		g: G,
41	) -> HashGraph<S, P, O> {
42		let len = g.len();
43
44		let mut subject_map = HashMap::new();
45		for (subject, predicates) in g.into_subjects() {
46			let mut predicate_map = HashMap::new();
47			for (predicate, objects) in predicates {
48				predicate_map.insert(predicate, objects.collect());
49			}
50
51			subject_map.insert(subject, predicate_map);
52		}
53
54		HashGraph {
55			table: subject_map,
56			len,
57		}
58	}
59
60	pub fn insert(&mut self, triple: Triple<S, P, O>) -> bool {
61		let (subject, predicate, object) = triple.into_parts();
62
63		let added = self
64			.table
65			.entry(subject)
66			.or_default()
67			.entry(predicate)
68			.or_default()
69			.insert(object);
70
71		if added {
72			self.len += 1;
73		}
74
75		added
76	}
77
78	pub fn absorb<G: crate::SizedGraph<Subject = S, Predicate = P, Object = O>>(
79		&mut self,
80		other: G,
81	) {
82		let subjects = other.into_subjects();
83
84		for (subject, predicates) in subjects {
85			let this_predicates = self.table.entry(subject).or_default();
86			for (predicate, objects) in predicates {
87				let this_objects = this_predicates.entry(predicate).or_default();
88				for object in objects {
89					if this_objects.insert(object) {
90						self.len += 1
91					}
92				}
93			}
94		}
95	}
96
97	pub fn remove<
98		T: ?Sized + Equivalent<S> + Hash,
99		U: ?Sized + Equivalent<P> + Hash,
100		V: ?Sized + Equivalent<O> + Hash,
101	>(
102		&mut self,
103		Triple(s, p, o): Triple<&T, &U, &V>,
104	) {
105		if let Some(predicates) = self.table.get_mut(s) {
106			if let Some(objects) = predicates.get_mut(p) {
107				if objects.remove(o) {
108					self.len -= 1;
109					if objects.is_empty() {
110						predicates.remove(p).unwrap();
111						if predicates.is_empty() {
112							self.table.remove(s);
113						}
114					}
115				}
116			}
117		}
118	}
119
120	pub fn take<
121		T: ?Sized + Equivalent<S> + Hash,
122		U: ?Sized + Equivalent<P> + Hash,
123		V: ?Sized + Equivalent<O> + Hash,
124	>(
125		&mut self,
126		Triple(s, p, o): Triple<&T, &U, &V>,
127	) -> Option<Triple<S, P, O>>
128	where
129		S: Clone,
130		P: Clone,
131	{
132		if let Some(predicates) = self.table.get_mut(s) {
133			if let Some(objects) = predicates.get_mut(p) {
134				if let Some(o) = objects.take(o) {
135					let (s, p) = if objects.is_empty() {
136						let p = predicates.remove_entry(p).unwrap().0;
137						let s = if predicates.is_empty() {
138							self.table.remove_entry(s).unwrap().0
139						} else {
140							self.table.get_key_value(s).unwrap().0.clone()
141						};
142
143						(s, p)
144					} else {
145						let p = predicates.get_key_value(p).unwrap().0.clone();
146						let s = self.table.get_key_value(s).unwrap().0.clone();
147						(s, p)
148					};
149
150					self.len -= 1;
151					return Some(Triple(s, p, o));
152				}
153			}
154		}
155
156		None
157	}
158
159	pub fn take_match<
160		T: ?Sized + Equivalent<S> + Hash,
161		U: ?Sized + Equivalent<P> + Hash,
162		V: ?Sized + Equivalent<O> + Hash,
163	>(
164		&mut self,
165		Triple(s, p, o): Triple<Option<&T>, Option<&U>, Option<&V>>,
166	) -> Option<Triple<S, P, O>>
167	where
168		S: Clone,
169		P: Clone,
170		O: Clone,
171	{
172		fn take_object_match<O: Clone + Eq + Hash, V: ?Sized + Equivalent<O> + Hash>(
173			objects: &mut HashSet<O>,
174			o: Option<&V>,
175		) -> Option<O> {
176			match o {
177				Some(o) => objects.take(o),
178				None => objects.iter().next().cloned().map(|o| {
179					objects.remove::<O>(&o);
180					o
181				}),
182			}
183		}
184
185		fn take_predicate_match<
186			P: Clone + Eq + Hash,
187			O: Clone + Eq + Hash,
188			U: ?Sized + Equivalent<P> + Hash,
189			V: ?Sized + Equivalent<O> + Hash,
190		>(
191			predicates: &mut HashMap<P, HashSet<O>>,
192			p: Option<&U>,
193			o: Option<&V>,
194		) -> Option<(P, O)> {
195			match p {
196				Some(p) => {
197					let objects = predicates.get_mut(p)?;
198					let o = take_object_match(objects, o)?;
199
200					let p = if objects.is_empty() {
201						predicates.remove_entry(p).unwrap().0
202					} else {
203						predicates.get_key_value(p).unwrap().0.clone()
204					};
205
206					Some((p, o))
207				}
208				None => {
209					for (p, objects) in &mut *predicates {
210						if let Some(o) = take_object_match(objects, o) {
211							let p = p.clone();
212
213							if objects.is_empty() {
214								predicates.remove::<P>(&p);
215							}
216
217							return Some((p, o));
218						}
219					}
220
221					None
222				}
223			}
224		}
225
226		match s {
227			Some(s) => {
228				let predicates = self.table.get_mut(s)?;
229				let (p, o) = take_predicate_match(predicates, p, o)?;
230
231				let s = if predicates.is_empty() {
232					self.table.remove_entry(s).unwrap().0
233				} else {
234					self.table.get_key_value(s).unwrap().0.clone()
235				};
236
237				self.len -= 1;
238				Some(Triple(s, p, o))
239			}
240			None => {
241				for (s, predicates) in &mut self.table {
242					if let Some((p, o)) = take_predicate_match(predicates, p, o) {
243						let s = s.clone();
244
245						if predicates.is_empty() {
246							self.table.remove::<S>(&s);
247						}
248
249						self.len -= 1;
250						return Some(Triple(s, p, o));
251					}
252				}
253
254				None
255			}
256		}
257	}
258
259	pub fn view<'a, A>(&'a self, subject: &'a S, access: A) -> GraphView<'a, Self, A> {
260		crate::Graph::view(self, subject, access)
261	}
262}
263
264impl<S, P, O> HashGraph<S, P, O> {
265	pub fn triples(&self) -> Iter<S, P, O> {
266		Iter {
267			subjects: self.subjects(),
268			subject: None,
269			predicates: None,
270			predicate: None,
271			objects: None,
272		}
273	}
274
275	pub fn subjects(&self) -> Subjects<S, P, O> {
276		Subjects {
277			it: self.table.iter(),
278		}
279	}
280
281	pub fn predicates(&self, subject: &S) -> Predicates<P, O>
282	where
283		S: Eq + Hash,
284	{
285		match self.table.get(subject) {
286			Some(map) => Predicates {
287				it: Some(map.iter()),
288			},
289			None => Predicates { it: None },
290		}
291	}
292
293	pub fn objects(&self, subject: &S, predicate: &P) -> Objects<O>
294	where
295		S: Eq + Hash,
296		P: Eq + Hash,
297	{
298		match self.table.get(subject) {
299			Some(map) => match map.get(predicate) {
300				Some(map) => Objects {
301					it: Some(map.iter()),
302				},
303				None => Objects { it: None },
304			},
305			None => Objects { it: None },
306		}
307	}
308
309	pub fn contains(&self, Triple(subject, predicate, object): Triple<&S, &P, &O>) -> bool
310	where
311		S: Eq + Hash,
312		P: Eq + Hash,
313		O: Eq + Hash,
314	{
315		match self.table.get(subject) {
316			Some(map) => match map.get(predicate) {
317				Some(map) => map.contains(object),
318				None => false,
319			},
320			None => false,
321		}
322	}
323
324	pub fn into_triples(self) -> IntoIter<S, P, O> {
325		IntoIter {
326			subjects: self.into_subjects(),
327			subject: None,
328			predicates: None,
329			predicate: None,
330			objects: None,
331		}
332	}
333
334	pub fn into_subjects(self) -> IntoSubjects<S, P, O> {
335		IntoSubjects {
336			it: self.table.into_iter(),
337		}
338	}
339
340	pub fn into_predicates(mut self, subject: &S) -> IntoPredicates<P, O>
341	where
342		S: Eq + Hash,
343	{
344		match self.table.remove(subject) {
345			Some(map) => IntoPredicates {
346				it: Some(map.into_iter()),
347			},
348			None => IntoPredicates { it: None },
349		}
350	}
351
352	pub fn into_objects(mut self, subject: &S, predicate: &P) -> IntoObjects<O>
353	where
354		S: Eq + Hash,
355		P: Eq + Hash,
356	{
357		match self.table.remove(subject) {
358			Some(mut map) => match map.remove(predicate) {
359				Some(map) => IntoObjects {
360					it: Some(map.into_iter()),
361				},
362				None => IntoObjects { it: None },
363			},
364			None => IntoObjects { it: None },
365		}
366	}
367}
368
369impl<S: Eq + Hash, P: Eq + Hash, O: Eq + Hash> crate::Graph for HashGraph<S, P, O> {
370	type Subject = S;
371	type Predicate = P;
372	type Object = O;
373
374	type Objects<'a> = Objects<'a, O> where
375		Self: 'a,
376		O: 'a;
377	type Predicates<'a> = Predicates<'a, P, O> where
378		Self: 'a,
379		P: 'a,
380		O: 'a;
381	type Subjects<'a> = Subjects<'a, S, P, O> where
382		Self: 'a,
383		S: 'a,
384		P: 'a,
385		O: 'a;
386	type Triples<'a> = Iter<'a, S, P, O> where
387		Self: 'a,
388		S: 'a,
389		P: 'a,
390		O: 'a;
391
392	type PatternMatching<'a, 'p> = GraphPatternMatching<'a, 'p, S, P, O> where
393		Self: 'a,
394		S: 'p,
395		P: 'p,
396		O: 'p;
397
398	#[inline(always)]
399	fn len(&self) -> usize {
400		self.len()
401	}
402
403	fn triples(&self) -> Iter<S, P, O> {
404		self.triples()
405	}
406
407	fn subjects(&self) -> Subjects<S, P, O> {
408		self.subjects()
409	}
410
411	fn predicates(&self, subject: &S) -> Predicates<P, O> {
412		self.predicates(subject)
413	}
414
415	fn objects(&self, subject: &S, predicate: &P) -> Objects<O> {
416		self.objects(subject, predicate)
417	}
418
419	fn contains(&self, triple: Triple<&S, &P, &O>) -> bool {
420		self.contains(triple)
421	}
422
423	fn pattern_matching<'p>(
424		&self,
425		pattern: Triple<
426			Option<&'p Self::Subject>,
427			Option<&'p Self::Predicate>,
428			Option<&'p Self::Object>,
429		>,
430	) -> Self::PatternMatching<'_, 'p> {
431		GraphPatternMatching::new(self, pattern)
432	}
433}
434
435impl<S: Eq + Hash, P: Eq + Hash, O: Eq + Hash> HashGraph<S, P, O> {
436	crate::macros::reflect_graph_impl!();
437}
438
439impl<'a, S, P, O> std::iter::IntoIterator for &'a HashGraph<S, P, O> {
440	type IntoIter = Iter<'a, S, P, O>;
441	type Item = Triple<&'a S, &'a P, &'a O>;
442
443	fn into_iter(self) -> Self::IntoIter {
444		self.triples()
445	}
446}
447
448impl<S: Clone + Eq + Hash, P: Clone + Eq + Hash, O: Eq + Hash> crate::SizedGraph
449	for HashGraph<S, P, O>
450{
451	type IntoObjects = IntoObjects<O>;
452	type IntoPredicates = IntoPredicates<P, O>;
453	type IntoSubjects = IntoSubjects<S, P, O>;
454	type IntoTriples = IntoIter<S, P, O>;
455
456	fn into_triples(self) -> IntoIter<S, P, O> {
457		self.into_triples()
458	}
459
460	fn into_subjects(self) -> IntoSubjects<S, P, O> {
461		self.into_subjects()
462	}
463
464	fn into_predicates(self, subject: &S) -> IntoPredicates<P, O> {
465		self.into_predicates(subject)
466	}
467
468	fn into_objects(self, subject: &S, predicate: &P) -> IntoObjects<O> {
469		self.into_objects(subject, predicate)
470	}
471}
472
473impl<S: Clone, P: Clone, O> IntoIterator for HashGraph<S, P, O> {
474	type IntoIter = IntoIter<S, P, O>;
475	type Item = Triple<S, P, O>;
476
477	fn into_iter(self) -> Self::IntoIter {
478		self.into_triples()
479	}
480}
481
482impl<S: Eq + Hash, P: Eq + Hash, O: Eq + Hash> crate::MutableGraph for HashGraph<S, P, O> {
483	fn insert(&mut self, triple: Triple<S, P, O>) -> bool {
484		self.insert(triple)
485	}
486
487	fn remove(
488		&mut self,
489		triple: Triple<
490			&<Self as crate::Graph>::Subject,
491			&<Self as crate::Graph>::Predicate,
492			&<Self as crate::Graph>::Object,
493		>,
494	) {
495		self.remove(triple)
496	}
497
498	fn absorb<G: crate::SizedGraph<Subject = S, Predicate = P, Object = O>>(&mut self, other: G) {
499		self.absorb(other)
500	}
501}
502
503impl<
504		S: Clone + Eq + Hash,
505		P: Clone + Eq + Hash,
506		O: Clone + Eq + Hash,
507		T: ?Sized + Equivalent<S> + Hash,
508		U: ?Sized + Equivalent<P> + Hash,
509		V: ?Sized + Equivalent<O> + Hash,
510	> crate::GraphTake<T, U, V> for HashGraph<S, P, O>
511{
512	fn take(
513		&mut self,
514		triple: Triple<&T, &U, &V>,
515	) -> Option<Triple<Self::Subject, Self::Predicate, Self::Object>> {
516		self.take(triple)
517	}
518
519	fn take_match(
520		&mut self,
521		triple: Triple<Option<&T>, Option<&U>, Option<&V>>,
522	) -> Option<Triple<Self::Subject, Self::Predicate, Self::Object>> {
523		self.take_match(triple)
524	}
525}
526
527impl<S: fmt::Debug, P: fmt::Debug, O: fmt::Debug> fmt::Debug for HashGraph<S, P, O> {
528	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
529		write!(f, "{{")?;
530
531		for (i, rdf_types::Triple(s, p, o)) in self.triples().enumerate() {
532			if i > 0 {
533				write!(f, ",")?;
534			}
535
536			write!(f, " {s:?} {p:?} {o:?}")?;
537		}
538
539		write!(f, "  }}")
540	}
541}
542
543#[derive(Educe)]
544#[educe(Clone)]
545pub struct Subjects<'a, S, P, O> {
546	it: hashbrown::hash_map::Iter<'a, S, HashMap<P, HashSet<O>>>,
547}
548
549impl<'a, S, P, O> Iterator for Subjects<'a, S, P, O> {
550	type Item = (&'a S, Predicates<'a, P, O>);
551
552	fn next(&mut self) -> Option<Self::Item> {
553		self.it.next().map(|(subject, map)| {
554			(
555				subject,
556				Predicates {
557					it: Some(map.iter()),
558				},
559			)
560		})
561	}
562}
563
564pub struct IntoSubjects<S, P, O> {
565	it: hashbrown::hash_map::IntoIter<S, HashMap<P, HashSet<O>>>,
566}
567
568impl<S, P, O> Iterator for IntoSubjects<S, P, O> {
569	type Item = (S, IntoPredicates<P, O>);
570
571	fn next(&mut self) -> Option<Self::Item> {
572		self.it.next().map(|(subject, map)| {
573			(
574				subject,
575				IntoPredicates {
576					it: Some(map.into_iter()),
577				},
578			)
579		})
580	}
581}
582
583#[derive(Educe)]
584#[educe(Clone)]
585pub struct Predicates<'a, P, O> {
586	it: Option<hashbrown::hash_map::Iter<'a, P, HashSet<O>>>,
587}
588
589impl<'a, P, O> Iterator for Predicates<'a, P, O> {
590	type Item = (&'a P, Objects<'a, O>);
591
592	fn next(&mut self) -> Option<Self::Item> {
593		match &mut self.it {
594			Some(it) => it.next().map(|(predicate, set)| {
595				(
596					predicate,
597					Objects {
598						it: Some(set.iter()),
599					},
600				)
601			}),
602			None => None,
603		}
604	}
605}
606
607pub struct IntoPredicates<P, O> {
608	it: Option<hashbrown::hash_map::IntoIter<P, HashSet<O>>>,
609}
610
611impl<P, O> Iterator for IntoPredicates<P, O> {
612	type Item = (P, IntoObjects<O>);
613
614	fn next(&mut self) -> Option<Self::Item> {
615		match &mut self.it {
616			Some(it) => it.next().map(|(predicate, set)| {
617				(
618					predicate,
619					IntoObjects {
620						it: Some(set.into_iter()),
621					},
622				)
623			}),
624			None => None,
625		}
626	}
627}
628
629#[derive(Educe)]
630#[educe(Clone)]
631pub struct Objects<'a, O> {
632	it: Option<hashbrown::hash_set::Iter<'a, O>>,
633}
634
635impl<'a, O> Iterator for Objects<'a, O> {
636	type Item = &'a O;
637
638	fn next(&mut self) -> Option<Self::Item> {
639		match &mut self.it {
640			Some(it) => it.next(),
641			None => None,
642		}
643	}
644}
645
646pub struct IntoObjects<O> {
647	it: Option<hashbrown::hash_set::IntoIter<O>>,
648}
649
650impl<O> Iterator for IntoObjects<O> {
651	type Item = O;
652
653	fn next(&mut self) -> Option<Self::Item> {
654		match &mut self.it {
655			Some(it) => it.next(),
656			None => None,
657		}
658	}
659}
660
661#[derive(Educe)]
662#[educe(Clone)]
663pub struct Iter<'a, S, P, O> {
664	subjects: Subjects<'a, S, P, O>,
665	subject: Option<&'a S>,
666	predicates: Option<Predicates<'a, P, O>>,
667	predicate: Option<&'a P>,
668	objects: Option<Objects<'a, O>>,
669}
670
671impl<'a, S, P, O> Iterator for Iter<'a, S, P, O> {
672	type Item = Triple<&'a S, &'a P, &'a O>;
673
674	fn next(&mut self) -> Option<Self::Item> {
675		loop {
676			match &mut self.objects {
677				Some(objects) => match objects.next() {
678					Some(object) => {
679						return Some(Triple(
680							self.subject.unwrap(),
681							self.predicate.unwrap(),
682							object,
683						))
684					}
685					None => {
686						self.objects = None;
687					}
688				},
689				None => match &mut self.predicates {
690					Some(predicates) => match predicates.next() {
691						Some((predicate, objects)) => {
692							self.predicate = Some(predicate);
693							self.objects = Some(objects)
694						}
695						None => {
696							self.predicates = None;
697							self.predicate = None;
698						}
699					},
700					None => match self.subjects.next() {
701						Some((subject, predicates)) => {
702							self.subject = Some(subject);
703							self.predicates = Some(predicates)
704						}
705						None => return None,
706					},
707				},
708			}
709		}
710	}
711}
712
713pub struct IntoIter<S, P, O> {
714	subjects: IntoSubjects<S, P, O>,
715	subject: Option<S>,
716	predicates: Option<IntoPredicates<P, O>>,
717	predicate: Option<P>,
718	objects: Option<IntoObjects<O>>,
719}
720
721impl<S: Clone, P: Clone, O> Iterator for IntoIter<S, P, O> {
722	type Item = Triple<S, P, O>;
723
724	fn next(&mut self) -> Option<Self::Item> {
725		loop {
726			match &mut self.objects {
727				Some(objects) => match objects.next() {
728					Some(object) => {
729						return Some(Triple(
730							self.subject.clone().unwrap(),
731							self.predicate.clone().unwrap(),
732							object,
733						))
734					}
735					None => {
736						self.objects = None;
737					}
738				},
739				None => match &mut self.predicates {
740					Some(predicates) => match predicates.next() {
741						Some((predicate, objects)) => {
742							self.predicate = Some(predicate);
743							self.objects = Some(objects)
744						}
745						None => {
746							self.predicates = None;
747							self.predicate = None;
748						}
749					},
750					None => match self.subjects.next() {
751						Some((subject, predicates)) => {
752							self.subject = Some(subject);
753							self.predicates = Some(predicates)
754						}
755						None => return None,
756					},
757				},
758			}
759		}
760	}
761}
762
763impl<S: Eq + Hash, P: Eq + Hash, O: Eq + Hash> std::iter::FromIterator<Triple<S, P, O>>
764	for HashGraph<S, P, O>
765{
766	fn from_iter<I: IntoIterator<Item = Triple<S, P, O>>>(iter: I) -> Self {
767		let mut ds = Self::new();
768		ds.extend(iter);
769		ds
770	}
771}
772
773impl<S: Eq + Hash, P: Eq + Hash, O: Eq + Hash> std::iter::Extend<Triple<S, P, O>>
774	for HashGraph<S, P, O>
775{
776	fn extend<I: IntoIterator<Item = Triple<S, P, O>>>(&mut self, iter: I) {
777		for quad in iter {
778			self.insert(quad);
779		}
780	}
781}