Skip to main content

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}