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}