reifydb_core/value/encoded/
uuid7.rs1use std::ptr;
5
6use reifydb_type::{Type, Uuid7};
7use uuid::Uuid;
8
9use crate::value::encoded::{EncodedValues, EncodedValuesLayout};
10
11impl EncodedValuesLayout {
12 pub fn set_uuid7(&self, row: &mut EncodedValues, index: usize, value: Uuid7) {
13 let field = &self.fields[index];
14 debug_assert!(row.len() >= self.total_static_size());
15 debug_assert_eq!(field.r#type, Type::Uuid7);
16 row.set_valid(index, true);
17 unsafe {
18 ptr::write_unaligned(
20 row.make_mut().as_mut_ptr().add(field.offset) as *mut [u8; 16],
21 *value.as_bytes(),
22 );
23 }
24 }
25
26 pub fn get_uuid7(&self, row: &EncodedValues, index: usize) -> Uuid7 {
27 let field = &self.fields[index];
28 debug_assert!(row.len() >= self.total_static_size());
29 debug_assert_eq!(field.r#type, Type::Uuid7);
30 unsafe {
31 let bytes: [u8; 16] = ptr::read_unaligned(row.as_ptr().add(field.offset) as *const [u8; 16]);
33 Uuid7::from(Uuid::from_bytes(bytes))
34 }
35 }
36
37 pub fn try_get_uuid7(&self, row: &EncodedValues, index: usize) -> Option<Uuid7> {
38 if row.is_defined(index) && self.fields[index].r#type == Type::Uuid7 {
39 Some(self.get_uuid7(row, index))
40 } else {
41 None
42 }
43 }
44}
45
46#[cfg(test)]
47mod tests {
48 use std::time::Duration;
49
50 use reifydb_type::{Type, Uuid7};
51 use tokio::time::sleep;
52
53 use crate::value::encoded::EncodedValuesLayout;
54
55 #[test]
56 fn test_set_get_uuid7() {
57 let layout = EncodedValuesLayout::new(&[Type::Uuid7]);
58 let mut row = layout.allocate();
59
60 let uuid = Uuid7::generate();
61 layout.set_uuid7(&mut row, 0, uuid.clone());
62 assert_eq!(layout.get_uuid7(&row, 0), uuid);
63 }
64
65 #[test]
66 fn test_try_get_uuid7() {
67 let layout = EncodedValuesLayout::new(&[Type::Uuid7]);
68 let mut row = layout.allocate();
69
70 assert_eq!(layout.try_get_uuid7(&row, 0), None);
71
72 let uuid = Uuid7::generate();
73 layout.set_uuid7(&mut row, 0, uuid.clone());
74 assert_eq!(layout.try_get_uuid7(&row, 0), Some(uuid));
75 }
76
77 #[test]
78 fn test_multiple_generations() {
79 let layout = EncodedValuesLayout::new(&[Type::Uuid7]);
80
81 let mut uuids = Vec::new();
83 for _ in 0..10 {
84 let mut row = layout.allocate();
85 let uuid = Uuid7::generate();
86 layout.set_uuid7(&mut row, 0, uuid.clone());
87 let retrieved = layout.get_uuid7(&row, 0);
88 assert_eq!(retrieved, uuid);
89 uuids.push(uuid);
90 }
91
92 for i in 0..uuids.len() {
94 for j in (i + 1)..uuids.len() {
95 assert_ne!(uuids[i], uuids[j], "UUIDs should be unique");
96 }
97 }
98 }
99
100 #[test]
101 fn test_version_check() {
102 let layout = EncodedValuesLayout::new(&[Type::Uuid7]);
103 let mut row = layout.allocate();
104
105 let uuid = Uuid7::generate();
106 layout.set_uuid7(&mut row, 0, uuid.clone());
107 let retrieved = layout.get_uuid7(&row, 0);
108
109 assert_eq!(retrieved.get_version_num(), 7);
111 }
112
113 #[tokio::test]
114 async fn test_timestamp_ordering() {
115 let layout = EncodedValuesLayout::new(&[Type::Uuid7]);
116
117 let mut uuids = Vec::new();
120 for _ in 0..5 {
121 let mut row = layout.allocate();
122 let uuid = Uuid7::generate();
123 layout.set_uuid7(&mut row, 0, uuid.clone());
124 let retrieved = layout.get_uuid7(&row, 0);
125 assert_eq!(retrieved, uuid);
126 uuids.push(uuid);
127
128 sleep(Duration::from_millis(1)).await;
130 }
131
132 for i in 1..uuids.len() {
134 assert!(uuids[i].as_bytes() >= uuids[i - 1].as_bytes(), "UUID7s should be timestamp-ordered");
135 }
136 }
137
138 #[test]
139 fn test_mixed_with_other_types() {
140 let layout = EncodedValuesLayout::new(&[Type::Uuid7, Type::Boolean, Type::Uuid7, Type::Int4]);
141 let mut row = layout.allocate();
142
143 let uuid1 = Uuid7::generate();
144 let uuid2 = Uuid7::generate();
145
146 layout.set_uuid7(&mut row, 0, uuid1.clone());
147 layout.set_bool(&mut row, 1, true);
148 layout.set_uuid7(&mut row, 2, uuid2.clone());
149 layout.set_i32(&mut row, 3, 42);
150
151 assert_eq!(layout.get_uuid7(&row, 0), uuid1);
152 assert_eq!(layout.get_bool(&row, 1), true);
153 assert_eq!(layout.get_uuid7(&row, 2), uuid2);
154 assert_eq!(layout.get_i32(&row, 3), 42);
155 }
156
157 #[test]
158 fn test_undefined_handling() {
159 let layout = EncodedValuesLayout::new(&[Type::Uuid7, Type::Uuid7]);
160 let mut row = layout.allocate();
161
162 let uuid = Uuid7::generate();
163 layout.set_uuid7(&mut row, 0, uuid.clone());
164
165 assert_eq!(layout.try_get_uuid7(&row, 0), Some(uuid));
166 assert_eq!(layout.try_get_uuid7(&row, 1), None);
167
168 layout.set_undefined(&mut row, 0);
169 assert_eq!(layout.try_get_uuid7(&row, 0), None);
170 }
171
172 #[test]
173 fn test_persistence() {
174 let layout = EncodedValuesLayout::new(&[Type::Uuid7]);
175 let mut row = layout.allocate();
176
177 let uuid = Uuid7::generate();
178 let uuid_string = uuid.to_string();
179
180 layout.set_uuid7(&mut row, 0, uuid.clone());
181 let retrieved = layout.get_uuid7(&row, 0);
182
183 assert_eq!(retrieved, uuid);
184 assert_eq!(retrieved.to_string(), uuid_string);
185 assert_eq!(retrieved.as_bytes(), uuid.as_bytes());
186 }
187
188 #[test]
189 fn test_clone_consistency() {
190 let layout = EncodedValuesLayout::new(&[Type::Uuid7]);
191 let mut row = layout.allocate();
192
193 let original_uuid = Uuid7::generate();
194 layout.set_uuid7(&mut row, 0, original_uuid.clone());
195
196 let retrieved_uuid = layout.get_uuid7(&row, 0);
197 assert_eq!(retrieved_uuid, original_uuid);
198
199 assert_eq!(retrieved_uuid.as_bytes(), original_uuid.as_bytes());
201 }
202
203 #[test]
204 fn test_multiple_fields() {
205 let layout = EncodedValuesLayout::new(&[Type::Uuid7, Type::Uuid7, Type::Uuid7]);
206 let mut row = layout.allocate();
207
208 let uuid1 = Uuid7::generate();
209 let uuid2 = Uuid7::generate();
210 let uuid3 = Uuid7::generate();
211
212 layout.set_uuid7(&mut row, 0, uuid1.clone());
213 layout.set_uuid7(&mut row, 1, uuid2.clone());
214 layout.set_uuid7(&mut row, 2, uuid3.clone());
215
216 assert_eq!(layout.get_uuid7(&row, 0), uuid1);
217 assert_eq!(layout.get_uuid7(&row, 1), uuid2);
218 assert_eq!(layout.get_uuid7(&row, 2), uuid3);
219
220 assert_ne!(uuid1, uuid2);
222 assert_ne!(uuid1, uuid3);
223 assert_ne!(uuid2, uuid3);
224 }
225
226 #[test]
227 fn test_format_consistency() {
228 let layout = EncodedValuesLayout::new(&[Type::Uuid7]);
229 let mut row = layout.allocate();
230
231 let uuid = Uuid7::generate();
232 let original_string = uuid.to_string();
233
234 layout.set_uuid7(&mut row, 0, uuid.clone());
235 let retrieved = layout.get_uuid7(&row, 0);
236 let retrieved_string = retrieved.to_string();
237
238 assert_eq!(original_string, retrieved_string);
239
240 assert_eq!(original_string.len(), 36);
242 assert_eq!(original_string.matches('-').count(), 4);
243 }
244
245 #[test]
246 fn test_byte_level_storage() {
247 let layout = EncodedValuesLayout::new(&[Type::Uuid7]);
248 let mut row = layout.allocate();
249
250 let uuid = Uuid7::generate();
251 let original_bytes = *uuid.as_bytes();
252
253 layout.set_uuid7(&mut row, 0, uuid.clone());
254 let retrieved = layout.get_uuid7(&row, 0);
255 let retrieved_bytes = *retrieved.as_bytes();
256
257 assert_eq!(original_bytes, retrieved_bytes);
258
259 assert_eq!(original_bytes.len(), 16);
261 assert_eq!(retrieved_bytes.len(), 16);
262 }
263
264 #[tokio::test]
265 async fn test_time_based_properties() {
266 let layout = EncodedValuesLayout::new(&[Type::Uuid7]);
267
268 let uuid1 = Uuid7::generate();
270 sleep(Duration::from_millis(2)).await;
271 let uuid2 = Uuid7::generate();
272
273 let mut row1 = layout.allocate();
274 let mut row2 = layout.allocate();
275
276 layout.set_uuid7(&mut row1, 0, uuid1.clone());
277 layout.set_uuid7(&mut row2, 0, uuid2.clone());
278
279 let retrieved1 = layout.get_uuid7(&row1, 0);
280 let retrieved2 = layout.get_uuid7(&row2, 0);
281
282 assert!(retrieved2.as_bytes() > retrieved1.as_bytes());
284 }
285
286 #[test]
287 fn test_try_get_uuid7_wrong_type() {
288 let layout = EncodedValuesLayout::new(&[Type::Boolean]);
289 let mut row = layout.allocate();
290
291 layout.set_bool(&mut row, 0, true);
292
293 assert_eq!(layout.try_get_uuid7(&row, 0), None);
294 }
295}