simple_triplestore/traits/
triplestore.rs

1use itertools::Itertools;
2
3use crate::{
4    prelude::*,
5    traits::{IdType, Property},
6    EdgeOrder,
7};
8
9/// Wrapper type for errors produced by either self or other in [TripleStore::try_eq()]
10#[derive(Debug)]
11pub enum TryEqError<LeftError: std::fmt::Debug, RightError: std::fmt::Debug> {
12    Left(LeftError),
13    Right(RightError),
14}
15
16/// A trait representing a graph constructed of vertices and edges, collectively referred to as nodes.
17///
18/// Nodes and Edges may be annotated with any type which supports to [PropertyType].
19///
20/// By default includes:
21///   * [Insert][TripleStoreInsert]
22///   * [Remove][TripleStoreRemove]
23///   * [Iter][TripleStoreIter]
24///   * [IntoIter][TripleStoreIntoIter]
25///   * [Query][TripleStoreQuery]
26///   * [Extend][TripleStoreExtend]
27///
28/// Some implementations may also support:
29///   * [Merge][TripleStoreMerge]
30///   * [Set Operations][TripleStoreSetOps]
31///
32/// # Example
33///
34/// See [MemTripleStore] or [SledTripleStore] for usage.
35pub trait TripleStore<Id: IdType, NodeProps: Property, EdgeProps: Property>:
36    TripleStoreInsert<Id, NodeProps, EdgeProps>
37    + TripleStoreRemove<Id, NodeProps, EdgeProps>
38    + TripleStoreIter<Id, NodeProps, EdgeProps>
39    + TripleStoreIntoIter<Id, NodeProps, EdgeProps>
40    + TripleStoreQuery<Id, NodeProps, EdgeProps>
41    + TripleStoreExtend<Id, NodeProps, EdgeProps>
42{
43    fn try_eq<OError: std::fmt::Debug>(
44        &self,
45        other: &impl TripleStore<Id, NodeProps, EdgeProps, Error = OError>,
46    ) -> Result<bool, TryEqError<Self::Error, OError>> {
47        let (self_nodes, self_edges) = self.iter_nodes(EdgeOrder::SPO);
48        let self_nodes = self_nodes.map(|r| r.map_err(|e| TryEqError::Left(e)));
49        let self_edges = self_edges.map(|r| r.map_err(|e| TryEqError::Left(e)));
50
51        let (other_nodes, other_edges) = other.iter_nodes(EdgeOrder::SPO);
52        let other_nodes = other_nodes.map(|r| r.map_err(|e| TryEqError::Right(e)));
53        let other_edges = other_edges.map(|r| r.map_err(|e| TryEqError::Right(e)));
54
55        for zip in self_nodes.zip_longest(other_nodes) {
56            match zip {
57                itertools::EitherOrBoth::Both(left, right) => {
58                    let left = left?;
59                    let right = right?;
60                    if left != right {
61                        return Ok(false);
62                    }
63                }
64                _ => {
65                    return Ok(false);
66                }
67            }
68        }
69
70        for zip in self_edges.zip_longest(other_edges) {
71            match zip {
72                itertools::EitherOrBoth::Both(left, right) => {
73                    let left = left?;
74                    let right = right?;
75                    if left != right {
76                        return Ok(false);
77                    }
78                }
79                _ => {
80                    return Ok(false);
81                }
82            }
83        }
84
85        Ok(true)
86    }
87}