1use super::*;
3use crate::dataset::{DTerm, Dataset, MutableDataset, SetDataset};
4use crate::quad::Quad;
5use crate::term::{
6 matcher::{Any, GraphNameMatcher},
7 GraphName,
8};
9
10#[repr(transparent)]
14#[derive(Clone, Copy, Debug)]
15pub struct UnionGraph<T: Dataset>(T);
16
17impl<T: Dataset> UnionGraph<T> {
18 pub fn new(wrapped: T) -> Self {
20 UnionGraph(wrapped)
21 }
22
23 pub fn unwrap(self) -> T {
25 self.0
26 }
27}
28
29impl<T: Dataset> Graph for UnionGraph<T> {
30 type Triple<'x> = [DTerm<'x, T>; 3] where Self: 'x;
31 type Error = T::Error;
32
33 fn triples(&self) -> impl Iterator<Item = GResult<Self, Self::Triple<'_>>> + '_ {
34 self.0
35 .quads()
36 .map(|r| r.map(Quad::into_triple))
38 }
39
40 fn triples_matching<'s, S, P, O>(
41 &'s self,
42 sm: S,
43 pm: P,
44 om: O,
45 ) -> impl Iterator<Item = GResult<Self, Self::Triple<'s>>> + 's
46 where
47 S: TermMatcher + 's,
48 P: TermMatcher + 's,
49 O: TermMatcher + 's,
50 {
51 self.0
52 .quads_matching(sm, pm, om, Any)
53 .map(|r| r.map(Quad::into_triple))
55 }
56
57 fn subjects(&self) -> impl Iterator<Item = GResult<Self, GTerm<'_, Self>>> + '_ {
58 self.0.subjects()
59 }
60
61 fn predicates(&self) -> impl Iterator<Item = GResult<Self, GTerm<'_, Self>>> + '_ {
62 self.0.predicates()
63 }
64
65 fn objects(&self) -> impl Iterator<Item = GResult<Self, GTerm<'_, Self>>> + '_ {
66 self.0.objects()
67 }
68
69 fn iris(&self) -> impl Iterator<Item = GResult<Self, GTerm<'_, Self>>> + '_ {
70 self.0.iris()
71 }
72
73 fn blank_nodes(&self) -> impl Iterator<Item = GResult<Self, GTerm<'_, Self>>> + '_ {
74 self.0.blank_nodes()
75 }
76
77 fn literals(&self) -> impl Iterator<Item = GResult<Self, GTerm<'_, Self>>> + '_ {
78 self.0.literals()
79 }
80
81 fn quoted_triples<'s>(&'s self) -> Box<dyn Iterator<Item = GResult<Self, GTerm<'_, Self>>> + '_>
82 where
83 GTerm<'s, Self>: Clone,
84 {
85 self.0.quoted_triples()
86 }
87
88 fn variables(&self) -> impl Iterator<Item = GResult<Self, GTerm<'_, Self>>> + '_ {
89 self.0.variables()
90 }
91}
92
93#[derive(Clone, Copy, Debug)]
99pub struct PartialUnionGraph<D: Dataset, M: GraphNameMatcher> {
100 d: D,
101 m: M,
102}
103
104impl<D: Dataset, M: GraphNameMatcher + Copy> PartialUnionGraph<D, M> {
105 pub fn new(d: D, m: M) -> Self {
108 PartialUnionGraph { d, m }
109 }
110
111 pub fn unwrap(self) -> (D, M) {
113 (self.d, self.m)
114 }
115}
116
117impl<D: Dataset, M: GraphNameMatcher + Copy> Graph for PartialUnionGraph<D, M> {
118 type Triple<'x> = [DTerm<'x, D>; 3] where Self: 'x;
119 type Error = D::Error;
120
121 fn triples(&self) -> impl Iterator<Item = GResult<Self, Self::Triple<'_>>> + '_ {
122 self.d
123 .quads_matching(Any, Any, Any, self.m)
124 .map(|r| r.map(Quad::into_triple))
126 }
127
128 fn triples_matching<'s, S, P, O>(
129 &'s self,
130 sm: S,
131 pm: P,
132 om: O,
133 ) -> impl Iterator<Item = GResult<Self, Self::Triple<'s>>> + 's
134 where
135 S: TermMatcher + 's,
136 P: TermMatcher + 's,
137 O: TermMatcher + 's,
138 {
139 self.d
140 .quads_matching(sm, pm, om, self.m)
141 .map(|r| r.map(Quad::into_triple))
143 }
144}
145
146#[derive(Clone, Copy, Debug)]
156pub struct DatasetGraph<D: Dataset, G: Term> {
157 d: D,
158 g: GraphName<G>,
159}
160
161impl<D: Dataset, G: Term> DatasetGraph<D, G> {
162 pub fn new(d: D, g: GraphName<G>) -> Self {
165 DatasetGraph { d, g }
166 }
167
168 pub fn unwrap(self) -> (D, GraphName<G>) {
170 (self.d, self.g)
171 }
172
173 fn g(&self) -> GraphName<G::BorrowTerm<'_>> {
174 self.g.as_ref().map(|gn| gn.borrow_term())
175 }
176
177 fn gd(&mut self) -> (Option<G::BorrowTerm<'_>>, &mut D) {
178 (self.g.as_ref().map(|gn| gn.borrow_term()), &mut self.d)
179 }
180}
181
182impl<D: Dataset, G: Term> Graph for DatasetGraph<D, G> {
183 type Triple<'x> = [DTerm<'x, D>; 3] where Self: 'x;
184 type Error = D::Error;
185
186 fn triples(&self) -> impl Iterator<Item = GResult<Self, Self::Triple<'_>>> + '_ {
187 self.d
188 .quads_matching(Any, Any, Any, [self.g()])
189 .map(|r| r.map(Quad::into_triple))
191 }
192
193 fn triples_matching<'s, S, P, O>(
194 &'s self,
195 sm: S,
196 pm: P,
197 om: O,
198 ) -> impl Iterator<Item = GResult<Self, Self::Triple<'s>>> + 's
199 where
200 S: TermMatcher + 's,
201 P: TermMatcher + 's,
202 O: TermMatcher + 's,
203 {
204 self.d
205 .quads_matching(sm, pm, om, [self.g()])
206 .map(|r| r.map(Quad::into_triple))
208 }
209}
210
211impl<D: SetDataset, G: Term> SetGraph for DatasetGraph<D, G> {}
212
213impl<D: MutableDataset, G: Term> MutableGraph for DatasetGraph<D, G> {
214 type MutationError = D::MutationError;
215
216 fn insert<TS, TP, TO>(&mut self, s: TS, p: TP, o: TO) -> MgResult<Self, bool>
217 where
218 TS: Term,
219 TP: Term,
220 TO: Term,
221 {
222 let (g, d) = self.gd();
223 d.insert(s, p, o, g)
224 }
225
226 fn remove<TS, TP, TO>(&mut self, s: TS, p: TP, o: TO) -> MgResult<Self, bool>
227 where
228 TS: Term,
229 TP: Term,
230 TO: Term,
231 {
232 let (g, d) = self.gd();
233 d.remove(s, p, o, g)
234 }
235}
236
237#[cfg(test)]
238mod test {
239 use super::*;
240 use crate::quad::Spog;
241 use crate::term::{graph_name_eq, FromTerm};
242 use sophia_iri::Iri;
243 use std::collections::BTreeSet;
244
245 static G1: Iri<&'static str> = Iri::new_unchecked_const("http://example.com/g1");
246 static G2: Iri<&'static str> = Iri::new_unchecked_const("http://example.com/g2");
247 static G3: Iri<&'static str> = Iri::new_unchecked_const("http://example.com/g3");
248
249 type MyTerm = SimpleTerm<'static>;
250 type MyQuad = Spog<MyTerm>;
251 type MyDS = BTreeSet<MyQuad>;
252
253 #[derive(Clone, Copy, Debug)]
254 struct GM;
255 impl GraphNameMatcher for GM {
256 type Term = MyTerm;
257
258 fn matches<T2: Term + ?Sized>(&self, graph_name: GraphName<&T2>) -> bool {
259 graph_name_eq(graph_name.map(|gn| gn.borrow_term()), Some(G1))
260 || graph_name_eq(graph_name.map(|gn| gn.borrow_term()), Some(G2))
261 }
262 }
263
264 type MyUG = UnionGraph<MyDS>;
265 fn collect_union_graph<T: TripleSource>(mut ts: T) -> Result<MyUG, T::Error> {
266 let mut ds = MyDS::new();
267 ts.for_each_triple(|t| {
268 let [s, p, o] = t.spo();
269 ds.insert_quad(([s, p, o], Some(s))).unwrap();
270 })?;
271 Ok(ds.into_union_graph())
272 }
273 crate::test_immutable_graph_impl!(union_graph, MyUG, true, true, collect_union_graph);
274
275 type MyPUG = PartialUnionGraph<MyDS, GM>;
276 fn collect_partial_union_graph<T: TripleSource>(mut ts: T) -> Result<MyPUG, T::Error> {
277 let g1: GraphName<MyTerm> = Some(G1.into_term());
278 let g2: GraphName<MyTerm> = Some(G2.into_term());
279 let g3: GraphName<MyTerm> = Some(G3.into_term());
280 let mut ds = MyDS::new();
281 let mut b = true;
282 ts.for_each_triple(|t| {
283 let [s, p, o] = t.spo();
284 if b {
285 ds.insert_quad(([s, p, o].map(MyTerm::from_term), g1.clone()))
286 .unwrap();
287 ds.insert_quad(([o, p, s].map(MyTerm::from_term), g3.clone()))
288 .unwrap();
289 } else {
290 ds.insert_quad(([s, p, o].map(MyTerm::from_term), g2.clone()))
291 .unwrap();
292 }
293 b = !b;
294 })?;
295 Ok(PartialUnionGraph::new(ds, GM))
296 }
297 crate::test_immutable_graph_impl!(
298 partial_union_graph,
299 MyPUG,
300 true,
301 true,
302 collect_partial_union_graph
303 );
304
305 type MyDG = DatasetGraph<MyDS, MyTerm>;
306 fn collect_dataset_graph<T: TripleSource>(mut ts: T) -> Result<MyDG, T::Error> {
307 let g1: GraphName<MyTerm> = Some(G1.into_term());
308 let g2: GraphName<MyTerm> = Some(G2.into_term());
309 let mut ds = MyDS::new();
310 ts.for_each_triple(|t| {
311 let [s, p, o] = t.spo();
312 ds.insert_quad(([s, p, o].map(MyTerm::from_term), g1.clone()))
313 .unwrap();
314 ds.insert_quad(([o, p, s].map(MyTerm::from_term), g2.clone()))
315 .unwrap();
316 })?;
317 Ok(DatasetGraph::new(ds, g1))
318 }
319 crate::test_graph_impl!(dataset_graph, MyDG, true, true, collect_dataset_graph);
320
321 #[allow(dead_code)] fn check_trait_impls() {
323 let mut ds = MyDS::new();
324 let g1: Option<MyTerm> = Some(G1.into_term());
325
326 for _ in ds.graph(g1.clone()).triples() {}
328
329 let mut gm = ds.graph_mut(g1);
330 for _ in gm.triples() {}
332 gm.remove_triple([1, 2, 3]).unwrap();
334
335 for _ in ds.partial_union_graph(GM).triples() {}
337
338 for _ in ds.union_graph().triples() {}
340
341 for _ in ds.into_union_graph().triples() {}
343 }
344}