sophia_api/dataset/
_foreign_impl.rs

1use super::*;
2use crate::quad::{Gspo, QBorrowTerm, Spog};
3use crate::source::SourceError;
4use crate::term::FromTerm;
5use std::collections::{BTreeSet, HashSet};
6use std::convert::Infallible;
7use std::hash::{BuildHasher, Hash};
8
9//
10// foreign implementations
11//
12
13// reference to Dataset
14
15impl<'a, T: Dataset + ?Sized> Dataset for &'a T {
16    type Quad<'x> = T::Quad<'x> where Self: 'x;
17
18    type Error = T::Error;
19
20    fn quads(&self) -> impl Iterator<Item = DResult<Self, Self::Quad<'_>>> + '_ {
21        T::quads(*self)
22    }
23
24    fn quads_matching<'s, S, P, O, G>(
25        &'s self,
26        sm: S,
27        pm: P,
28        om: O,
29        gm: G,
30    ) -> impl Iterator<Item = DResult<Self, Self::Quad<'s>>> + 's
31    where
32        S: TermMatcher + 's,
33        P: TermMatcher + 's,
34        O: TermMatcher + 's,
35        G: GraphNameMatcher + 's,
36    {
37        T::quads_matching(*self, sm, pm, om, gm)
38    }
39
40    fn contains<TS, TP, TO, TG>(&self, s: TS, p: TP, o: TO, g: GraphName<TG>) -> DResult<Self, bool>
41    where
42        TS: Term,
43        TP: Term,
44        TO: Term,
45        TG: Term,
46    {
47        T::contains(*self, s, p, o, g)
48    }
49
50    fn subjects(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
51        T::subjects(*self)
52    }
53
54    fn predicates(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
55        T::predicates(*self)
56    }
57
58    fn objects(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
59        T::objects(*self)
60    }
61
62    fn graph_names(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
63        T::graph_names(*self)
64    }
65
66    fn iris(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
67        T::iris(*self)
68    }
69
70    fn blank_nodes(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
71        T::blank_nodes(*self)
72    }
73
74    fn literals(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
75        T::literals(*self)
76    }
77
78    fn quoted_triples<'s>(&'s self) -> Box<dyn Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_>
79    where
80        DTerm<'s, Self>: Clone,
81    {
82        T::quoted_triples(*self)
83    }
84
85    fn variables(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
86        T::variables(*self)
87    }
88}
89
90// NB: this one is required so that &'a mut T can also implement MutableDataset
91impl<'a, T: Dataset + ?Sized> Dataset for &'a mut T {
92    type Quad<'x> = T::Quad<'x> where Self: 'x;
93
94    type Error = T::Error;
95
96    fn quads(&self) -> impl Iterator<Item = DResult<Self, Self::Quad<'_>>> + '_ {
97        T::quads(*self)
98    }
99
100    fn quads_matching<'s, S, P, O, G>(
101        &'s self,
102        sm: S,
103        pm: P,
104        om: O,
105        gm: G,
106    ) -> impl Iterator<Item = DResult<Self, Self::Quad<'s>>> + 's
107    where
108        S: TermMatcher + 's,
109        P: TermMatcher + 's,
110        O: TermMatcher + 's,
111        G: GraphNameMatcher + 's,
112    {
113        T::quads_matching(*self, sm, pm, om, gm)
114    }
115
116    fn contains<TS, TP, TO, TG>(&self, s: TS, p: TP, o: TO, g: GraphName<TG>) -> DResult<Self, bool>
117    where
118        TS: Term,
119        TP: Term,
120        TO: Term,
121        TG: Term,
122    {
123        T::contains(*self, s, p, o, g)
124    }
125
126    fn subjects(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
127        T::subjects(*self)
128    }
129
130    fn predicates(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
131        T::predicates(*self)
132    }
133
134    fn objects(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
135        T::objects(*self)
136    }
137
138    fn graph_names(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
139        T::graph_names(*self)
140    }
141
142    fn iris(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
143        T::iris(*self)
144    }
145
146    fn blank_nodes(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
147        T::blank_nodes(*self)
148    }
149
150    fn literals(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
151        T::literals(*self)
152    }
153
154    fn quoted_triples<'s>(&'s self) -> Box<dyn Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_>
155    where
156        DTerm<'s, Self>: Clone,
157    {
158        T::quoted_triples(*self)
159    }
160
161    fn variables(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
162        T::variables(*self)
163    }
164}
165
166impl<T: MutableDataset + ?Sized> MutableDataset for &mut T {
167    type MutationError = T::MutationError;
168
169    fn insert<TS, TP, TO, TG>(
170        &mut self,
171        s: TS,
172        p: TP,
173        o: TO,
174        g: GraphName<TG>,
175    ) -> MdResult<Self, bool>
176    where
177        TS: Term,
178        TP: Term,
179        TO: Term,
180        TG: Term,
181    {
182        T::insert(*self, s, p, o, g)
183    }
184
185    fn remove<TS, TP, TO, TG>(
186        &mut self,
187        s: TS,
188        p: TP,
189        o: TO,
190        g: GraphName<TG>,
191    ) -> MdResult<Self, bool>
192    where
193        TS: Term,
194        TP: Term,
195        TO: Term,
196        TG: Term,
197    {
198        T::remove(*self, s, p, o, g)
199    }
200
201    fn insert_all<TS: QuadSource>(
202        &mut self,
203        src: TS,
204    ) -> StreamResult<usize, TS::Error, Self::MutationError> {
205        T::insert_all(*self, src)
206    }
207
208    fn remove_all<TS: QuadSource>(
209        &mut self,
210        src: TS,
211    ) -> StreamResult<usize, TS::Error, Self::MutationError> {
212        T::remove_all(*self, src)
213    }
214
215    fn remove_matching<S, P, O, G>(
216        &mut self,
217        ms: S,
218        mp: P,
219        mo: O,
220        mg: G,
221    ) -> Result<usize, Self::MutationError>
222    where
223        S: TermMatcher,
224        P: TermMatcher,
225        O: TermMatcher,
226        G: GraphNameMatcher,
227        Self::MutationError: From<Self::Error>,
228    {
229        T::remove_matching(*self, ms, mp, mo, mg)
230    }
231
232    fn retain_matching<S, P, O, G>(
233        &mut self,
234        ms: S,
235        mp: P,
236        mo: O,
237        mg: G,
238    ) -> Result<(), Self::MutationError>
239    where
240        S: TermMatcher,
241        P: TermMatcher,
242        O: TermMatcher,
243        G: GraphNameMatcher,
244        Self::MutationError: From<Self::Error>,
245    {
246        T::retain_matching(*self, ms, mp, mo, mg)
247    }
248}
249
250//
251// foreign implementations
252//
253
254// slice of quads
255
256impl<Q: Quad> Dataset for [Q] {
257    type Error = Infallible;
258    type Quad<'x> = Spog<QBorrowTerm<'x, Q>> where Self: 'x;
259
260    fn quads(&self) -> impl Iterator<Item = DResult<Self, Self::Quad<'_>>> + '_ {
261        self.iter().map(Quad::spog).map(Ok)
262    }
263}
264
265// Vec of quads
266
267impl<Q: Quad> Dataset for Vec<Q> {
268    type Error = Infallible;
269    type Quad<'x> = Spog<QBorrowTerm<'x, Q>> where Self: 'x;
270
271    fn quads(&self) -> impl Iterator<Item = DResult<Self, Self::Quad<'_>>> + '_ {
272        self[..].quads()
273    }
274}
275
276impl<T> CollectibleDataset for Vec<Spog<T>>
277where
278    T: Term + FromTerm,
279{
280    fn from_quad_source<TS: QuadSource>(
281        mut quads: TS,
282    ) -> StreamResult<Self, TS::Error, Self::Error> {
283        let min_cap = quads.size_hint_quads().0;
284        let mut v = Vec::with_capacity(min_cap);
285        quads
286            .for_each_quad(|q| {
287                v.push((
288                    [q.s().into_term(), q.p().into_term(), q.o().into_term()],
289                    q.g().map(Term::into_term),
290                ))
291            })
292            .map_err(SourceError)?;
293        Ok(v)
294    }
295}
296
297impl<T> MutableDataset for Vec<Spog<T>>
298where
299    T: Term + FromTerm,
300{
301    type MutationError = Infallible;
302
303    fn insert<TS, TP, TO, TG>(
304        &mut self,
305        s: TS,
306        p: TP,
307        o: TO,
308        g: GraphName<TG>,
309    ) -> MdResult<Self, bool>
310    where
311        TS: Term,
312        TP: Term,
313        TO: Term,
314        TG: Term,
315    {
316        self.push((
317            [s.into_term(), p.into_term(), o.into_term()],
318            g.map(Term::into_term),
319        ));
320        Ok(true)
321    }
322
323    fn remove<TS, TP, TO, TG>(
324        &mut self,
325        s: TS,
326        p: TP,
327        o: TO,
328        g: GraphName<TG>,
329    ) -> MdResult<Self, bool>
330    where
331        TS: Term,
332        TP: Term,
333        TO: Term,
334        TG: Term,
335    {
336        let s = s.borrow_term();
337        let p = p.borrow_term();
338        let o = o.borrow_term();
339        let g = g.as_ref().map(|gn| gn.borrow_term());
340        let mut i = 0;
341        while i < self.len() {
342            if self[i].matched_by([s], [p], [o], [g]) {
343                self.swap_remove(i);
344            } else {
345                i += 1;
346            }
347        }
348        Ok(true)
349    }
350}
351
352impl<T> CollectibleDataset for Vec<Gspo<T>>
353where
354    T: Term + FromTerm,
355{
356    fn from_quad_source<TS: QuadSource>(
357        mut quads: TS,
358    ) -> StreamResult<Self, TS::Error, Self::Error> {
359        let min_cap = quads.size_hint_quads().0;
360        let mut v = Vec::with_capacity(min_cap);
361        quads
362            .for_each_quad(|q| {
363                v.push((
364                    q.g().map(Term::into_term),
365                    [q.s().into_term(), q.p().into_term(), q.o().into_term()],
366                ))
367            })
368            .map_err(SourceError)?;
369        Ok(v)
370    }
371}
372
373impl<T> MutableDataset for Vec<Gspo<T>>
374where
375    T: Term + FromTerm,
376{
377    type MutationError = Infallible;
378
379    fn insert<TS, TP, TO, TG>(
380        &mut self,
381        s: TS,
382        p: TP,
383        o: TO,
384        g: GraphName<TG>,
385    ) -> MdResult<Self, bool>
386    where
387        TS: Term,
388        TP: Term,
389        TO: Term,
390        TG: Term,
391    {
392        self.push((
393            g.map(Term::into_term),
394            [s.into_term(), p.into_term(), o.into_term()],
395        ));
396        Ok(true)
397    }
398
399    fn remove<TS, TP, TO, TG>(
400        &mut self,
401        s: TS,
402        p: TP,
403        o: TO,
404        g: GraphName<TG>,
405    ) -> MdResult<Self, bool>
406    where
407        TS: Term,
408        TP: Term,
409        TO: Term,
410        TG: Term,
411    {
412        let s = s.borrow_term();
413        let p = p.borrow_term();
414        let o = o.borrow_term();
415        let g = g.as_ref().map(|gn| gn.borrow_term());
416        match self.iter().position(|q| q.matched_by([s], [p], [o], [g])) {
417            None => Ok(false),
418            Some(i) => {
419                self.swap_remove(i);
420                Ok(true)
421            }
422        }
423    }
424}
425
426// HashSet of quads
427
428impl<Q: Quad, S> Dataset for HashSet<Q, S> {
429    type Error = Infallible;
430    type Quad<'x> = Spog<QBorrowTerm<'x, Q>> where Self: 'x;
431
432    fn quads(&self) -> impl Iterator<Item = DResult<Self, Self::Quad<'_>>> + '_ {
433        self.iter().map(Quad::spog).map(Ok)
434    }
435}
436
437impl<T, S> CollectibleDataset for HashSet<Spog<T>, S>
438where
439    T: Term + Eq + FromTerm + Hash,
440    S: BuildHasher + Default,
441{
442    fn from_quad_source<TS: QuadSource>(
443        mut quads: TS,
444    ) -> StreamResult<Self, TS::Error, Self::Error> {
445        let min_cap = quads.size_hint_quads().0;
446        let mut s = HashSet::<_, S>::with_capacity_and_hasher(min_cap, S::default());
447        quads
448            .for_each_quad(|q| {
449                s.insert((
450                    [q.s().into_term(), q.p().into_term(), q.o().into_term()],
451                    q.g().map(Term::into_term),
452                ));
453            })
454            .map_err(SourceError)?;
455        Ok(s)
456    }
457}
458
459impl<T, S> MutableDataset for HashSet<Spog<T>, S>
460where
461    T: Term + Eq + FromTerm + Hash,
462    S: BuildHasher + Default,
463{
464    type MutationError = Infallible;
465
466    fn insert<TS, TP, TO, TG>(
467        &mut self,
468        s: TS,
469        p: TP,
470        o: TO,
471        g: GraphName<TG>,
472    ) -> MdResult<Self, bool>
473    where
474        TS: Term,
475        TP: Term,
476        TO: Term,
477        TG: Term,
478    {
479        Ok(self.insert((
480            [s.into_term(), p.into_term(), o.into_term()],
481            g.map(Term::into_term),
482        )))
483    }
484
485    fn remove<TS, TP, TO, TG>(
486        &mut self,
487        s: TS,
488        p: TP,
489        o: TO,
490        g: GraphName<TG>,
491    ) -> MdResult<Self, bool>
492    where
493        TS: Term,
494        TP: Term,
495        TO: Term,
496        TG: Term,
497    {
498        Ok(self.remove(&(
499            [s.into_term(), p.into_term(), o.into_term()],
500            g.map(Term::into_term),
501        )))
502    }
503}
504
505impl<T, S> CollectibleDataset for HashSet<Gspo<T>, S>
506where
507    T: Term + Eq + FromTerm + Hash,
508    S: BuildHasher + Default,
509{
510    fn from_quad_source<TS: QuadSource>(
511        mut quads: TS,
512    ) -> StreamResult<Self, TS::Error, Self::Error> {
513        let min_cap = quads.size_hint_quads().0;
514        let mut s = HashSet::<_, S>::with_capacity_and_hasher(min_cap, S::default());
515        quads
516            .for_each_quad(|q| {
517                s.insert((
518                    q.g().map(Term::into_term),
519                    [q.s().into_term(), q.p().into_term(), q.o().into_term()],
520                ));
521            })
522            .map_err(SourceError)?;
523        Ok(s)
524    }
525}
526
527impl<T, S> MutableDataset for HashSet<Gspo<T>, S>
528where
529    T: Term + Eq + FromTerm + Hash,
530    S: BuildHasher + Default,
531{
532    type MutationError = Infallible;
533
534    fn insert<TS, TP, TO, TG>(
535        &mut self,
536        s: TS,
537        p: TP,
538        o: TO,
539        g: GraphName<TG>,
540    ) -> MdResult<Self, bool>
541    where
542        TS: Term,
543        TP: Term,
544        TO: Term,
545        TG: Term,
546    {
547        Ok(self.insert((
548            g.map(Term::into_term),
549            [s.into_term(), p.into_term(), o.into_term()],
550        )))
551    }
552
553    fn remove<TS, TP, TO, TG>(
554        &mut self,
555        s: TS,
556        p: TP,
557        o: TO,
558        g: GraphName<TG>,
559    ) -> MdResult<Self, bool>
560    where
561        TS: Term,
562        TP: Term,
563        TO: Term,
564        TG: Term,
565    {
566        Ok(self.remove(&(
567            g.map(Term::into_term),
568            [s.into_term(), p.into_term(), o.into_term()],
569        )))
570    }
571}
572
573impl<T: Quad, S> SetDataset for HashSet<T, S> {}
574
575// BTreeSet of quads
576
577/// NB: This is a straightforward and minimal implementation,
578/// not taking advantage of the order of terms to optimize [`Dataset::quads_matching`]
579/// nor other methods.
580impl<Q: Quad> Dataset for BTreeSet<Q> {
581    type Error = Infallible;
582    type Quad<'x> = Spog<QBorrowTerm<'x, Q>> where Self: 'x;
583
584    fn quads(&self) -> impl Iterator<Item = DResult<Self, Self::Quad<'_>>> + '_ {
585        self.iter().map(Quad::spog).map(Ok)
586    }
587}
588
589impl<T> CollectibleDataset for BTreeSet<Spog<T>>
590where
591    T: Term + FromTerm + Ord,
592{
593    fn from_quad_source<TS: QuadSource>(
594        mut quads: TS,
595    ) -> StreamResult<Self, TS::Error, Self::Error> {
596        let mut s = BTreeSet::new();
597        quads
598            .for_each_quad(|q| {
599                s.insert((
600                    [q.s().into_term(), q.p().into_term(), q.o().into_term()],
601                    q.g().map(Term::into_term),
602                ));
603            })
604            .map_err(SourceError)?;
605        Ok(s)
606    }
607}
608
609impl<T> MutableDataset for BTreeSet<Spog<T>>
610where
611    T: Term + FromTerm + Ord,
612{
613    type MutationError = Infallible;
614
615    fn insert<TS, TP, TO, TG>(
616        &mut self,
617        s: TS,
618        p: TP,
619        o: TO,
620        g: GraphName<TG>,
621    ) -> MdResult<Self, bool>
622    where
623        TS: Term,
624        TP: Term,
625        TO: Term,
626        TG: Term,
627    {
628        Ok(self.insert((
629            [s.into_term(), p.into_term(), o.into_term()],
630            g.map(Term::into_term),
631        )))
632    }
633
634    fn remove<TS, TP, TO, TG>(
635        &mut self,
636        s: TS,
637        p: TP,
638        o: TO,
639        g: GraphName<TG>,
640    ) -> MdResult<Self, bool>
641    where
642        TS: Term,
643        TP: Term,
644        TO: Term,
645        TG: Term,
646    {
647        Ok(self.remove(&(
648            [s.into_term(), p.into_term(), o.into_term()],
649            g.map(Term::into_term),
650        )))
651    }
652}
653
654impl<T> CollectibleDataset for BTreeSet<Gspo<T>>
655where
656    T: Term + FromTerm + Ord,
657{
658    fn from_quad_source<TS: QuadSource>(
659        mut quads: TS,
660    ) -> StreamResult<Self, TS::Error, Self::Error> {
661        let mut s = BTreeSet::new();
662        quads
663            .for_each_quad(|q| {
664                s.insert((
665                    q.g().map(Term::into_term),
666                    [q.s().into_term(), q.p().into_term(), q.o().into_term()],
667                ));
668            })
669            .map_err(SourceError)?;
670        Ok(s)
671    }
672}
673
674impl<T> MutableDataset for BTreeSet<Gspo<T>>
675where
676    T: Term + FromTerm + Ord,
677{
678    type MutationError = Infallible;
679
680    fn insert<TS, TP, TO, TG>(
681        &mut self,
682        s: TS,
683        p: TP,
684        o: TO,
685        g: GraphName<TG>,
686    ) -> MdResult<Self, bool>
687    where
688        TS: Term,
689        TP: Term,
690        TO: Term,
691        TG: Term,
692    {
693        Ok(self.insert((
694            g.map(Term::into_term),
695            [s.into_term(), p.into_term(), o.into_term()],
696        )))
697    }
698
699    fn remove<TS, TP, TO, TG>(
700        &mut self,
701        s: TS,
702        p: TP,
703        o: TO,
704        g: GraphName<TG>,
705    ) -> MdResult<Self, bool>
706    where
707        TS: Term,
708        TP: Term,
709        TO: Term,
710        TG: Term,
711    {
712        Ok(self.remove(&(
713            g.map(Term::into_term),
714            [s.into_term(), p.into_term(), o.into_term()],
715        )))
716    }
717}
718
719impl<T: Quad> SetDataset for BTreeSet<T> {}
720
721#[cfg(test)]
722mod test {
723    use super::*;
724    // NB: implementation of Dataset by &D and &mut D are not tested,
725    // as the code is trivial to review.
726
727    // NB: implementation of Dataset by [Q] is tested indirectly,
728    // as the implementation of Dataset by Vec<Q> relies on it.
729
730    type VecAsDataset = Vec<Spog<SimpleTerm<'static>>>;
731    crate::test_dataset_impl!(vec, VecAsDataset, false);
732
733    // the following is only to test the test macro with is_gen=false
734    #[cfg(feature = "all_tests")]
735    crate::test_immutable_dataset_impl!(vec_strict, VecAsDataset, false, false);
736
737    #[cfg(feature = "all_tests")]
738    type HashSetAsDataset = HashSet<Spog<SimpleTerm<'static>>>;
739    #[cfg(feature = "all_tests")]
740    crate::test_dataset_impl!(hashset, HashSetAsDataset);
741
742    #[cfg(feature = "all_tests")]
743    type HashSetAsDataset2 = HashSet<Gspo<SimpleTerm<'static>>>;
744    #[cfg(feature = "all_tests")]
745    crate::test_dataset_impl!(hashset2, HashSetAsDataset2);
746
747    #[cfg(feature = "all_tests")]
748    type BTreeSetAsDataset = BTreeSet<Spog<SimpleTerm<'static>>>;
749    #[cfg(feature = "all_tests")]
750    crate::test_dataset_impl!(btreeset, BTreeSetAsDataset);
751
752    #[cfg(feature = "all_tests")]
753    type BTreeSetAsDataset2 = BTreeSet<Gspo<SimpleTerm<'static>>>;
754    #[cfg(feature = "all_tests")]
755    crate::test_dataset_impl!(btreeset2, BTreeSetAsDataset2);
756}