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