reifydb_value/value/container/
uuid_array.rs1use std::{mem::ManuallyDrop, ops::Deref, slice};
5
6use arrow_array::{Array, FixedSizeBinaryArray};
7use arrow_buffer::Buffer;
8use uuid::Uuid;
9
10use crate::value::{
11 Value,
12 identity::IdentityId,
13 is::IsUuid,
14 uuid::{Uuid4, Uuid7},
15 value_type::ValueType,
16};
17
18pub const UUID_WIDTH: usize = 16;
19
20fn rows(array: &FixedSizeBinaryArray) -> &[u8] {
21 assert_eq!(
22 array.value_length() as usize,
23 UUID_WIDTH,
24 "uuid column must hold {UUID_WIDTH} byte values, found {}",
25 array.value_length()
26 );
27 &array.value_data()[..array.len() * UUID_WIDTH]
28}
29
30pub fn uuid4s(array: &FixedSizeBinaryArray) -> &[Uuid4] {
31 let bytes = rows(array);
32 unsafe { slice::from_raw_parts(bytes.as_ptr().cast::<Uuid4>(), array.len()) }
34}
35
36pub fn uuid7s(array: &FixedSizeBinaryArray) -> &[Uuid7] {
37 let bytes = rows(array);
38 unsafe { slice::from_raw_parts(bytes.as_ptr().cast::<Uuid7>(), array.len()) }
40}
41
42pub fn identity_ids(array: &FixedSizeBinaryArray) -> &[IdentityId] {
43 let bytes = rows(array);
44 unsafe { slice::from_raw_parts(bytes.as_ptr().cast::<IdentityId>(), array.len()) }
46}
47
48fn collect_rows<T: IsUuid + Copy>(values: impl IntoIterator<Item = T>) -> FixedSizeBinaryArray {
49 const { assert!(size_of::<T>() == UUID_WIDTH && align_of::<T>() == 1) };
50 let mut rows = ManuallyDrop::new(values.into_iter().collect::<Vec<T>>());
51 let (ptr, len, capacity) = (rows.as_mut_ptr(), rows.len(), rows.capacity());
52 let bytes = unsafe { Vec::from_raw_parts(ptr.cast::<u8>(), len * UUID_WIDTH, capacity * UUID_WIDTH) };
54 FixedSizeBinaryArray::new(UUID_WIDTH as i32, Buffer::from_vec(bytes), None)
55}
56
57pub fn uuid4_array(values: impl IntoIterator<Item = Uuid4>) -> FixedSizeBinaryArray {
58 collect_rows(values)
59}
60
61pub fn uuid7_array(values: impl IntoIterator<Item = Uuid7>) -> FixedSizeBinaryArray {
62 collect_rows(values)
63}
64
65pub fn identity_id_array(values: impl IntoIterator<Item = IdentityId>) -> FixedSizeBinaryArray {
66 collect_rows(values)
67}
68
69pub fn get_value<T>(values: &[T], index: usize) -> Value
70where
71 T: IsUuid + Copy + Deref<Target = Uuid>,
72{
73 if index < values.len() {
74 values[index].to_value()
75 } else {
76 Value::none()
77 }
78}
79
80pub fn identity_id_get_value(values: &[IdentityId], index: usize) -> Value {
81 if index < values.len() {
82 Value::IdentityId(values[index])
83 } else {
84 Value::none_of(ValueType::IdentityId)
85 }
86}
87
88pub fn as_string<T: IsUuid>(values: &[T], index: usize) -> String {
89 if index < values.len() {
90 values[index].to_string()
91 } else {
92 "none".to_string()
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn uuid7_array_takes_the_vec_allocation_without_copying() {
102 let mut values = Vec::with_capacity(8);
104 for i in 1..=3u128 {
105 values.push(Uuid7(Uuid::from_u128(0x0190_0000_0000_7000_8000_0000_0000_0000 | i)));
106 }
107 assert!(values.capacity() > values.len());
108 let expected = values.clone();
109 let ptr = values.as_ptr().cast::<u8>();
110
111 let array = uuid7_array(values);
112
113 assert_eq!(array.value_data().as_ptr(), ptr);
114 assert_eq!(array.len(), expected.len());
115 assert_eq!(uuid7s(&array), expected.as_slice());
116 for (i, value) in expected.iter().enumerate() {
117 assert_eq!(array.value(i), value.as_bytes());
118 }
119 }
120}