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