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