reifydb_core/value/encoded/
identity_id.rs1use std::ptr;
5
6use reifydb_type::{IdentityId, Type, Uuid7};
7use uuid::Uuid;
8
9use crate::value::encoded::{EncodedValues, EncodedValuesLayout};
10
11impl EncodedValuesLayout {
12 pub fn set_identity_id(&self, row: &mut EncodedValues, index: usize, value: IdentityId) {
13 let field = &self.fields[index];
14 debug_assert!(row.len() >= self.total_static_size());
15 debug_assert_eq!(field.r#type, Type::IdentityId);
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_identity_id(&self, row: &EncodedValues, index: usize) -> IdentityId {
27 let field = &self.fields[index];
28 debug_assert!(row.len() >= self.total_static_size());
29 debug_assert_eq!(field.r#type, Type::IdentityId);
30 unsafe {
31 let bytes: [u8; 16] = ptr::read_unaligned(row.as_ptr().add(field.offset) as *const [u8; 16]);
33 let uuid = Uuid::from_bytes(bytes);
34 let uuid7 = Uuid7::from(uuid);
35 IdentityId::from(uuid7)
36 }
37 }
38
39 pub fn try_get_identity_id(&self, row: &EncodedValues, index: usize) -> Option<IdentityId> {
40 if row.is_defined(index) && self.fields[index].r#type == Type::IdentityId {
41 Some(self.get_identity_id(row, index))
42 } else {
43 None
44 }
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use std::time::Duration;
51
52 use reifydb_type::{IdentityId, Type};
53 use tokio::time::sleep;
54
55 use crate::value::encoded::EncodedValuesLayout;
56
57 #[test]
58 fn test_set_get_identity_id() {
59 let layout = EncodedValuesLayout::new(&[Type::IdentityId]);
60 let mut row = layout.allocate();
61
62 let id = IdentityId::generate();
63 layout.set_identity_id(&mut row, 0, id.clone());
64 assert_eq!(layout.get_identity_id(&row, 0), id);
65 }
66
67 #[test]
68 fn test_try_get_identity_id() {
69 let layout = EncodedValuesLayout::new(&[Type::IdentityId]);
70 let mut row = layout.allocate();
71
72 assert_eq!(layout.try_get_identity_id(&row, 0), None);
73
74 let id = IdentityId::generate();
75 layout.set_identity_id(&mut row, 0, id.clone());
76 assert_eq!(layout.try_get_identity_id(&row, 0), Some(id));
77 }
78
79 #[test]
80 fn test_multiple_generations() {
81 let layout = EncodedValuesLayout::new(&[Type::IdentityId]);
82
83 let mut ids = Vec::new();
85 for _ in 0..10 {
86 let mut row = layout.allocate();
87 let id = IdentityId::generate();
88 layout.set_identity_id(&mut row, 0, id.clone());
89 let retrieved = layout.get_identity_id(&row, 0);
90 assert_eq!(retrieved, id);
91 ids.push(id);
92 }
93
94 for i in 0..ids.len() {
96 for j in (i + 1)..ids.len() {
97 assert_ne!(ids[i], ids[j], "Identity IDs should be unique");
98 }
99 }
100 }
101
102 #[test]
103 fn test_uuid7_properties() {
104 let layout = EncodedValuesLayout::new(&[Type::IdentityId]);
105 let mut row = layout.allocate();
106
107 let id = IdentityId::generate();
108 layout.set_identity_id(&mut row, 0, id.clone());
109 let retrieved = layout.get_identity_id(&row, 0);
110
111 assert_eq!(retrieved.get_version_num(), 7);
113 assert_eq!(id.get_version_num(), 7);
114 }
115
116 #[tokio::test]
117 async fn test_timestamp_ordering() {
118 let layout = EncodedValuesLayout::new(&[Type::IdentityId]);
119
120 let mut ids = Vec::new();
123 for _ in 0..5 {
124 let mut row = layout.allocate();
125 let id = IdentityId::generate();
126 layout.set_identity_id(&mut row, 0, id.clone());
127 let retrieved = layout.get_identity_id(&row, 0);
128 assert_eq!(retrieved, id);
129 ids.push(id);
130
131 sleep(Duration::from_millis(1)).await;
133 }
134
135 for i in 1..ids.len() {
137 assert!(ids[i].as_bytes() >= ids[i - 1].as_bytes(), "Identity IDs should be timestamp-ordered");
138 }
139 }
140
141 #[test]
142 fn test_mixed_with_other_types() {
143 let layout = EncodedValuesLayout::new(&[Type::IdentityId, Type::Boolean, Type::IdentityId, Type::Int4]);
144 let mut row = layout.allocate();
145
146 let id1 = IdentityId::generate();
147 let id2 = IdentityId::generate();
148
149 layout.set_identity_id(&mut row, 0, id1.clone());
150 layout.set_bool(&mut row, 1, true);
151 layout.set_identity_id(&mut row, 2, id2.clone());
152 layout.set_i32(&mut row, 3, 42);
153
154 assert_eq!(layout.get_identity_id(&row, 0), id1);
155 assert_eq!(layout.get_bool(&row, 1), true);
156 assert_eq!(layout.get_identity_id(&row, 2), id2);
157 assert_eq!(layout.get_i32(&row, 3), 42);
158 }
159
160 #[test]
161 fn test_undefined_handling() {
162 let layout = EncodedValuesLayout::new(&[Type::IdentityId, Type::IdentityId]);
163 let mut row = layout.allocate();
164
165 let id = IdentityId::generate();
166 layout.set_identity_id(&mut row, 0, id.clone());
167
168 assert_eq!(layout.try_get_identity_id(&row, 0), Some(id));
169 assert_eq!(layout.try_get_identity_id(&row, 1), None);
170
171 layout.set_undefined(&mut row, 0);
172 assert_eq!(layout.try_get_identity_id(&row, 0), None);
173 }
174
175 #[test]
176 fn test_persistence() {
177 let layout = EncodedValuesLayout::new(&[Type::IdentityId]);
178 let mut row = layout.allocate();
179
180 let id = IdentityId::generate();
181 let id_string = id.to_string();
182
183 layout.set_identity_id(&mut row, 0, id.clone());
184 let retrieved = layout.get_identity_id(&row, 0);
185
186 assert_eq!(retrieved, id);
187 assert_eq!(retrieved.to_string(), id_string);
188 assert_eq!(retrieved.as_bytes(), id.as_bytes());
189 }
190
191 #[test]
192 fn test_clone_consistency() {
193 let layout = EncodedValuesLayout::new(&[Type::IdentityId]);
194 let mut row = layout.allocate();
195
196 let original_id = IdentityId::generate();
197 layout.set_identity_id(&mut row, 0, original_id.clone());
198
199 let retrieved_id = layout.get_identity_id(&row, 0);
200 assert_eq!(retrieved_id, original_id);
201
202 assert_eq!(retrieved_id.as_bytes(), original_id.as_bytes());
205 }
206
207 #[test]
208 fn test_multiple_fields() {
209 let layout = EncodedValuesLayout::new(&[Type::IdentityId, Type::IdentityId, Type::IdentityId]);
210 let mut row = layout.allocate();
211
212 let id1 = IdentityId::generate();
213 let id2 = IdentityId::generate();
214 let id3 = IdentityId::generate();
215
216 layout.set_identity_id(&mut row, 0, id1.clone());
217 layout.set_identity_id(&mut row, 1, id2.clone());
218 layout.set_identity_id(&mut row, 2, id3.clone());
219
220 assert_eq!(layout.get_identity_id(&row, 0), id1);
221 assert_eq!(layout.get_identity_id(&row, 1), id2);
222 assert_eq!(layout.get_identity_id(&row, 2), id3);
223
224 assert_ne!(id1, id2);
226 assert_ne!(id1, id3);
227 assert_ne!(id2, id3);
228 }
229
230 #[test]
231 fn test_format_consistency() {
232 let layout = EncodedValuesLayout::new(&[Type::IdentityId]);
233 let mut row = layout.allocate();
234
235 let id = IdentityId::generate();
236 let original_string = id.to_string();
237
238 layout.set_identity_id(&mut row, 0, id.clone());
239 let retrieved = layout.get_identity_id(&row, 0);
240 let retrieved_string = retrieved.to_string();
241
242 assert_eq!(original_string, retrieved_string);
243
244 assert_eq!(original_string.len(), 36);
247 assert_eq!(original_string.matches('-').count(), 4);
248 }
249
250 #[test]
251 fn test_byte_level_storage() {
252 let layout = EncodedValuesLayout::new(&[Type::IdentityId]);
253 let mut row = layout.allocate();
254
255 let id = IdentityId::generate();
256 let original_bytes = *id.as_bytes();
257
258 layout.set_identity_id(&mut row, 0, id.clone());
259 let retrieved = layout.get_identity_id(&row, 0);
260 let retrieved_bytes = *retrieved.as_bytes();
261
262 assert_eq!(original_bytes, retrieved_bytes);
263
264 assert_eq!(original_bytes.len(), 16);
266 assert_eq!(retrieved_bytes.len(), 16);
267 }
268
269 #[tokio::test]
270 async fn test_time_based_properties() {
271 let layout = EncodedValuesLayout::new(&[Type::IdentityId]);
272
273 let id1 = IdentityId::generate();
275 sleep(Duration::from_millis(2)).await;
276 let id2 = IdentityId::generate();
277
278 let mut row1 = layout.allocate();
279 let mut row2 = layout.allocate();
280
281 layout.set_identity_id(&mut row1, 0, id1.clone());
282 layout.set_identity_id(&mut row2, 0, id2.clone());
283
284 let retrieved1 = layout.get_identity_id(&row1, 0);
285 let retrieved2 = layout.get_identity_id(&row2, 0);
286
287 assert!(retrieved2.as_bytes() > retrieved1.as_bytes());
290 }
291
292 #[test]
293 fn test_as_primary_key() {
294 let layout = EncodedValuesLayout::new(&[
295 Type::IdentityId, Type::Utf8, Type::Int4, ]);
299 let mut row = layout.allocate();
300
301 let primary_key = IdentityId::generate();
303 layout.set_identity_id(&mut row, 0, primary_key.clone());
304 layout.set_utf8(&mut row, 1, "John Doe");
305 layout.set_i32(&mut row, 2, 30);
306
307 assert_eq!(layout.get_identity_id(&row, 0), primary_key);
308 assert_eq!(layout.get_utf8(&row, 1), "John Doe");
309 assert_eq!(layout.get_i32(&row, 2), 30);
310
311 assert_eq!(primary_key.get_version_num(), 7);
313 }
314
315 #[test]
316 fn test_try_get_identity_id_wrong_type() {
317 let layout = EncodedValuesLayout::new(&[Type::Boolean]);
318 let mut row = layout.allocate();
319
320 layout.set_bool(&mut row, 0, true);
321
322 assert_eq!(layout.try_get_identity_id(&row, 0), None);
323 }
324}