triblespace_core/trible.rs
1//! Representation of a single knowledge graph edge.
2//!
3//! For layout details and edge semantics see the [Trible Structure](../book/src/deep-dive/trible-structure.md) chapter of the Tribles Book.
4
5mod fragment;
6mod tribleset;
7
8use std::convert::TryInto;
9
10use crate::id::ExclusiveId;
11use crate::id::Id;
12use crate::value::Value;
13use crate::value::ValueSchema;
14
15pub use fragment::Fragment;
16pub use tribleset::TribleSet;
17pub use tribleset::TribleSetFingerprint;
18
19/// The length of a trible in bytes.
20pub const TRIBLE_LEN: usize = 64;
21
22/// The start index of the entity in a trible.
23pub const E_START: usize = 0;
24/// The end index of the entity in a trible (inclusive).
25pub const E_END: usize = 15;
26
27/// The start index of the attribute in a trible.
28pub const A_START: usize = 16;
29/// The end index of the attribute in a trible (inclusive).
30pub const A_END: usize = 31;
31
32/// The start index of the value in a trible.
33pub const V_START: usize = 32;
34/// The end index of the value in a trible (inclusive).
35pub const V_END: usize = 63;
36
37/// Fundamentally a trible is always a collection of 64 bytes.
38pub type RawTrible = [u8; TRIBLE_LEN];
39
40/// Fundamental 64-byte tuple of entity, attribute and value used throughout the
41/// knowledge graph.
42///
43/// See the [Trible Structure](../book/src/deep-dive/trible-structure.md)
44/// chapter of the Tribles Book for a detailed discussion of the layout and its
45/// design rationale.
46#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
47#[repr(transparent)]
48pub struct Trible {
49 pub data: RawTrible,
50}
51
52impl Trible {
53 /// Creates a new trible from an entity, an attribute, and a value.
54 ///
55 /// # Arguments
56 ///
57 /// * `e` - The entity of the trible.
58 /// * `a` - The attribute of the trible.
59 /// * `v` - The value of the trible.
60 ///
61 /// # Returns
62 ///
63 /// A new trible.
64 ///
65 /// # Example
66 ///
67 /// ```
68 /// use triblespace_core::prelude::*;
69 /// use valueschemas::R256;
70 ///
71 /// let e = fucid();
72 /// let a = fucid();
73 /// let v: Value<R256> = R256::value_from(42);
74 /// let trible = Trible::new(&e, &a, &v);
75 /// ```
76 pub fn new<V: ValueSchema>(e: &ExclusiveId, a: &Id, v: &Value<V>) -> Trible {
77 let mut data = [0; TRIBLE_LEN];
78 data[E_START..=E_END].copy_from_slice(&e[..]);
79 data[A_START..=A_END].copy_from_slice(&a[..]);
80 data[V_START..=V_END].copy_from_slice(&v.raw[..]);
81
82 Self { data }
83 }
84
85 /// Creates a new trible from an entity, an attribute, and a value.
86 /// This is similar to [Trible::new], but takes a plain entity id instead of an owned id.
87 /// Allowing to circumvent the ownership system, which can be used to inject
88 /// data into a local knowledge graph without owning the entity.
89 /// This is useful for loading existing trible data, for example when loading
90 /// an existing [crate::trible::TribleSet] from a blob, or when declaring
91 /// a namespace.
92 ///
93 /// # Arguments
94 ///
95 /// * `e` - The entity of the trible.
96 /// * `a` - The attribute of the trible.
97 /// * `v` - The value of the trible.
98 ///
99 /// # Returns
100 ///
101 /// A new trible.
102 ///
103 /// # Example
104 ///
105 /// ```
106 /// use triblespace_core::prelude::*;
107 /// use valueschemas::R256;
108 ///
109 /// let e = fucid();
110 /// let a = fucid();
111 /// let v: Value<R256> = R256::value_from(42);
112 /// let trible = Trible::force(&e, &a, &v);
113 ///
114 /// assert_eq!(trible.e(), &*e);
115 /// ```
116 pub fn force<V: ValueSchema>(e: &Id, a: &Id, v: &Value<V>) -> Trible {
117 Trible::new(ExclusiveId::force_ref(e), a, v)
118 }
119
120 /// Creates a new trible from a raw trible (a 64-byte array).
121 /// It circumvents the ownership system, and is useful for loading existing trible data,
122 /// just like [Trible::force].
123 ///
124 /// # Arguments
125 ///
126 /// * `data` - The raw trible.
127 ///
128 /// # Returns
129 ///
130 /// A new trible if the entity and attribute are not nil
131 /// (i.e. they are not all zeroes), otherwise `None`.
132 ///
133 /// # Example
134 ///
135 /// ```
136 /// use triblespace_core::prelude::*;
137 ///
138 /// let data = [
139 /// // Entity
140 /// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
141 /// // Attribute
142 /// 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
143 /// // Value
144 /// 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
145 /// 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
146 /// ];
147 /// let trible = Trible::force_raw(data);
148 /// assert!(trible.is_some());
149 /// ```
150 pub fn force_raw(data: RawTrible) -> Option<Trible> {
151 if data[E_START..=E_END].iter().all(|&x| x == 0)
152 || data[A_START..=A_END].iter().all(|&x| x == 0)
153 {
154 return None;
155 }
156 Some(Self { data })
157 }
158
159 /// Transmutes a raw trible reference into a trible reference.
160 /// Circumvents the ownership system, and is useful for loading existing trible data,
161 /// just like [Trible::force] and [Trible::force_raw].
162 ///
163 /// # Arguments
164 ///
165 /// * `data` - The raw trible reference.
166 ///
167 /// # Returns
168 ///
169 /// A new trible reference if the entity and attribute are not nil
170 /// (i.e. they are not all zeroes), otherwise `None`.
171 ///
172 /// # Example
173 ///
174 /// ```
175 /// use triblespace_core::prelude::*;
176 ///
177 /// let data = [
178 /// // Entity
179 /// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
180 /// // Attribute
181 /// 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
182 /// // Value
183 /// 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
184 /// 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
185 /// ];
186 /// let trible = Trible::as_transmute_force_raw(&data);
187 /// assert!(trible.is_some());
188 /// ```
189 pub fn as_transmute_force_raw(data: &RawTrible) -> Option<&Self> {
190 if data[E_START..=E_END].iter().all(|&x| x == 0)
191 || data[A_START..=A_END].iter().all(|&x| x == 0)
192 {
193 return None;
194 }
195 Some(unsafe { std::mem::transmute::<&RawTrible, &Self>(data) })
196 }
197
198 /// Transmutes a raw trible reference into a trible reference.
199 /// Circumvents the ownership system, and does not check if the entity and attribute are nil.
200 /// Should only be used if it it certain that the `RawTrible` is actually valid.
201 pub fn as_transmute_raw_unchecked(data: &RawTrible) -> &Self {
202 unsafe { std::mem::transmute::<&RawTrible, &Self>(data) }
203 }
204
205 /// Returns the entity of the trible.
206 ///
207 /// # Returns
208 ///
209 /// The entity of the trible.
210 ///
211 /// # Example
212 ///
213 /// ```
214 /// use triblespace_core::prelude::*;
215 ///
216 /// let data = [
217 /// // Entity
218 /// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
219 /// // Attribute
220 /// 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
221 /// // Value
222 /// 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
223 /// 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
224 /// ];
225 /// let trible = Trible::force_raw(data).unwrap();
226 /// let entity = trible.e();
227 /// assert_eq!(entity, &Id::new([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]).unwrap());
228 /// ```
229 pub fn e(&self) -> &Id {
230 Id::as_transmute_raw(self.data[E_START..=E_END].try_into().unwrap()).unwrap()
231 }
232
233 /// Returns the attribute of the trible.
234 ///
235 /// # Returns
236 ///
237 /// The attribute of the trible.
238 ///
239 /// # Example
240 ///
241 /// ```
242 /// use triblespace_core::prelude::*;
243 ///
244 /// let data = [
245 /// // Entity
246 /// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
247 /// // Attribute
248 /// 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
249 /// // Value
250 /// 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
251 /// 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
252 /// ];
253 /// let trible = Trible::force_raw(data).unwrap();
254 /// let attribute = trible.a();
255 /// assert_eq!(attribute, &Id::new([16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]).unwrap());
256 /// ```
257 pub fn a(&self) -> &Id {
258 Id::as_transmute_raw(self.data[A_START..=A_END].try_into().unwrap()).unwrap()
259 }
260
261 /// Returns the value of the trible.
262 ///
263 /// # Returns
264 ///
265 /// The value of the trible.
266 ///
267 /// # Example
268 ///
269 /// ```
270 /// use triblespace_core::prelude::*;
271 /// use valueschemas::R256;
272 ///
273 /// let data = [
274 /// // Entity
275 /// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
276 /// // Attribute
277 /// 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
278 /// // Value
279 /// 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
280 /// 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
281 /// ];
282 /// let trible = Trible::force_raw(data).unwrap();
283 /// let value = trible.v::<R256>();
284 /// assert_eq!(value, &Value::new([32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
285 /// 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63]));
286 /// ```
287 pub fn v<V: ValueSchema>(&self) -> &Value<V> {
288 Value::as_transmute_raw(self.data[V_START..=V_END].try_into().unwrap())
289 }
290}
291
292crate::key_segmentation!(TribleSegmentation, TRIBLE_LEN, [16, 16, 32]);
293
294crate::key_schema!(EAVOrder, TribleSegmentation, TRIBLE_LEN, [0, 1, 2]);
295crate::key_schema!(EVAOrder, TribleSegmentation, TRIBLE_LEN, [0, 2, 1]);
296crate::key_schema!(AEVOrder, TribleSegmentation, TRIBLE_LEN, [1, 0, 2]);
297crate::key_schema!(AVEOrder, TribleSegmentation, TRIBLE_LEN, [1, 2, 0]);
298crate::key_schema!(VEAOrder, TribleSegmentation, TRIBLE_LEN, [2, 0, 1]);
299crate::key_schema!(VAEOrder, TribleSegmentation, TRIBLE_LEN, [2, 1, 0]);
300
301#[cfg(test)]
302mod tests {
303 use super::*;
304 use crate::patch::KeySchema;
305
306 #[rustfmt::skip]
307 #[test]
308 fn order_eav() {
309 let key_bytes = [
310 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
311 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
312 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
313 ];
314 let tree_bytes = [
315 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
316 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
317 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
318 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
319 ];
320 assert_eq!(EAVOrder::tree_ordered(&key_bytes), tree_bytes);
321 assert_eq!(EAVOrder::key_ordered(&tree_bytes), key_bytes);
322 }
323
324 #[rustfmt::skip]
325 #[test]
326 fn order_eva() {
327 let key_bytes = [
328 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
329 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
330 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
331 ];
332 let tree_bytes = [
333 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
334 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
335 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
336 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
337 ];
338 assert_eq!(EVAOrder::tree_ordered(&key_bytes), tree_bytes);
339 assert_eq!(EVAOrder::key_ordered(&tree_bytes), key_bytes);
340 }
341
342 #[rustfmt::skip]
343 #[test]
344 fn order_aev() {
345 let key_bytes = [
346 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
347 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
348 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
349 ];
350 let tree_bytes = [
351 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 4, 5, 6, 7,
352 8, 9, 10, 11, 12, 13, 14, 15, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
353 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
354 ];
355 assert_eq!(AEVOrder::tree_ordered(&key_bytes), tree_bytes);
356 assert_eq!(AEVOrder::key_ordered(&tree_bytes), key_bytes);
357 }
358
359 #[rustfmt::skip]
360 #[test]
361 fn order_ave() {
362 let key_bytes = [
363 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
364 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
365 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
366 ];
367 let tree_bytes = [
368 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
369 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
370 60, 61, 62, 63, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
371 ];
372 assert_eq!(AVEOrder::tree_ordered(&key_bytes), tree_bytes);
373 assert_eq!(AVEOrder::key_ordered(&tree_bytes), key_bytes);
374 }
375
376 #[rustfmt::skip]
377 #[test]
378 fn order_vea() {
379 let key_bytes = [
380 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
381 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
382 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
383 ];
384 let tree_bytes = [
385 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
386 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
387 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
388 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
389 ];
390 assert_eq!(VEAOrder::tree_ordered(&key_bytes), tree_bytes);
391 assert_eq!(VEAOrder::key_ordered(&tree_bytes), key_bytes);
392 }
393
394 #[rustfmt::skip]
395 #[test]
396 fn order_vae() {
397 let key_bytes = [
398 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
399 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
400 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
401 ];
402 let tree_bytes = [
403 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
404 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
405 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
406 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
407 ];
408 assert_eq!(VAEOrder::tree_ordered(&key_bytes), tree_bytes);
409 assert_eq!(VAEOrder::key_ordered(&tree_bytes), key_bytes);
410 }
411}