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}