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}