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}