Skip to main content

triblespace_core/trible/
fragment.rs

1use std::ops::{Add, AddAssign, Deref};
2
3use crate::id::Id;
4use crate::id::RawId;
5use crate::patch::Entry;
6use crate::patch::PATCH;
7
8use super::Trible;
9use super::TribleSet;
10
11/// A rooted (or multi-root) fragment of a knowledge graph.
12///
13/// A fragment is a [`TribleSet`] plus a (possibly empty) set of "exported" entity
14/// ids that act as entry points into the contained facts. Exports are not
15/// privileged in the graph model itself; they are simply the ids the producer
16/// wants to hand back to the caller as the fragment's interface.
17#[derive(Debug, Clone, Default, PartialEq, Eq)]
18pub struct Fragment {
19    exports: PATCH<16>,
20    facts: TribleSet,
21}
22
23impl Fragment {
24    /// Creates an empty fragment with no exports and no facts.
25    pub fn empty() -> Self {
26        Self::default()
27    }
28
29    /// Creates a fragment that exports a single root id.
30    pub fn rooted(root: Id, facts: TribleSet) -> Self {
31        let mut exports = PATCH::<16>::new();
32        let raw: RawId = root.into();
33        exports.insert(&Entry::new(&raw));
34        Self { exports, facts }
35    }
36
37    /// Creates a fragment with the given exported ids.
38    ///
39    /// Export ids are canonicalized as a set (duplicates are ignored). Empty
40    /// exports are allowed.
41    pub fn new<I>(exports: I, facts: TribleSet) -> Self
42    where
43        I: IntoIterator<Item = Id>,
44    {
45        let mut export_set = PATCH::<16>::new();
46        for id in exports {
47            let raw: RawId = id.into();
48            export_set.insert(&Entry::new(&raw));
49        }
50        Self {
51            exports: export_set,
52            facts,
53        }
54    }
55
56    /// Returns the exported ids for this fragment, in deterministic (lexicographic) order.
57    pub fn exports(&self) -> impl Iterator<Item = Id> + '_ {
58        self.exports
59            .iter_ordered()
60            .map(|raw| Id::new(*raw).expect("export ids are non-nil"))
61    }
62
63    /// Returns the single exported id if this fragment is rooted.
64    pub fn root(&self) -> Option<Id> {
65        if self.exports.len() == 1 {
66            let raw = self
67                .exports
68                .iter_ordered()
69                .next()
70                .expect("len() == 1 implies a first element exists");
71            Some(Id::new(*raw).expect("export ids are non-nil"))
72        } else {
73            None
74        }
75    }
76
77    pub fn facts(&self) -> &TribleSet {
78        &self.facts
79    }
80
81    pub fn into_facts(self) -> TribleSet {
82        self.facts
83    }
84
85    pub fn into_parts(self) -> (PATCH<16>, TribleSet) {
86        (self.exports, self.facts)
87    }
88}
89
90impl Deref for Fragment {
91    type Target = TribleSet;
92
93    fn deref(&self) -> &Self::Target {
94        &self.facts
95    }
96}
97
98impl<'a> IntoIterator for &'a Fragment {
99    type Item = &'a Trible;
100    type IntoIter = super::tribleset::TribleSetIterator<'a>;
101
102    fn into_iter(self) -> Self::IntoIter {
103        self.facts.iter()
104    }
105}
106
107impl AddAssign for Fragment {
108    fn add_assign(&mut self, rhs: Self) {
109        self.facts += rhs.facts;
110        self.exports.union(rhs.exports);
111    }
112}
113
114impl AddAssign<TribleSet> for Fragment {
115    fn add_assign(&mut self, rhs: TribleSet) {
116        self.facts += rhs;
117    }
118}
119
120impl Add for Fragment {
121    type Output = Self;
122
123    fn add(mut self, rhs: Self) -> Self::Output {
124        self += rhs;
125        self
126    }
127}
128
129impl Add<TribleSet> for Fragment {
130    type Output = Self;
131
132    fn add(mut self, rhs: TribleSet) -> Self::Output {
133        self += rhs;
134        self
135    }
136}
137
138impl AddAssign<Fragment> for TribleSet {
139    fn add_assign(&mut self, rhs: Fragment) {
140        self.union(rhs.facts);
141    }
142}
143
144impl Add<Fragment> for TribleSet {
145    type Output = Self;
146
147    fn add(mut self, rhs: Fragment) -> Self::Output {
148        self += rhs;
149        self
150    }
151}
152
153impl From<Fragment> for TribleSet {
154    fn from(value: Fragment) -> Self {
155        value.facts
156    }
157}