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