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) {
41 Some(self.get_identity_id(row, index))
42 } else {
43 None
44 }
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use reifydb_type::{IdentityId, Type};
51
52 use crate::value::encoded::EncodedValuesLayout;
53
54 #[test]
55 fn test_set_get_identity_id() {
56 let layout = EncodedValuesLayout::new(&[Type::IdentityId]);
57 let mut row = layout.allocate();
58
59 let id = IdentityId::generate();
60 layout.set_identity_id(&mut row, 0, id.clone());
61 assert_eq!(layout.get_identity_id(&row, 0), id);
62 }
63
64 #[test]
65 fn test_try_get_identity_id() {
66 let layout = EncodedValuesLayout::new(&[Type::IdentityId]);
67 let mut row = layout.allocate();
68
69 assert_eq!(layout.try_get_identity_id(&row, 0), None);
70
71 let id = IdentityId::generate();
72 layout.set_identity_id(&mut row, 0, id.clone());
73 assert_eq!(layout.try_get_identity_id(&row, 0), Some(id));
74 }
75
76 #[test]
77 fn test_multiple_generations() {
78 let layout = EncodedValuesLayout::new(&[Type::IdentityId]);
79
80 let mut ids = Vec::new();
82 for _ in 0..10 {
83 let mut row = layout.allocate();
84 let id = IdentityId::generate();
85 layout.set_identity_id(&mut row, 0, id.clone());
86 let retrieved = layout.get_identity_id(&row, 0);
87 assert_eq!(retrieved, id);
88 ids.push(id);
89 }
90
91 for i in 0..ids.len() {
93 for j in (i + 1)..ids.len() {
94 assert_ne!(ids[i], ids[j], "Identity IDs should be unique");
95 }
96 }
97 }
98
99 #[test]
100 fn test_uuid7_properties() {
101 let layout = EncodedValuesLayout::new(&[Type::IdentityId]);
102 let mut row = layout.allocate();
103
104 let id = IdentityId::generate();
105 layout.set_identity_id(&mut row, 0, id.clone());
106 let retrieved = layout.get_identity_id(&row, 0);
107
108 assert_eq!(retrieved.get_version_num(), 7);
110 assert_eq!(id.get_version_num(), 7);
111 }
112
113 #[test]
114 fn test_timestamp_ordering() {
115 let layout = EncodedValuesLayout::new(&[Type::IdentityId]);
116
117 let mut ids = Vec::new();
120 for _ in 0..5 {
121 let mut row = layout.allocate();
122 let id = IdentityId::generate();
123 layout.set_identity_id(&mut row, 0, id.clone());
124 let retrieved = layout.get_identity_id(&row, 0);
125 assert_eq!(retrieved, id);
126 ids.push(id);
127
128 std::thread::sleep(std::time::Duration::from_millis(1));
130 }
131
132 for i in 1..ids.len() {
134 assert!(ids[i].as_bytes() >= ids[i - 1].as_bytes(), "Identity IDs should be timestamp-ordered");
135 }
136 }
137
138 #[test]
139 fn test_mixed_with_other_types() {
140 let layout = EncodedValuesLayout::new(&[Type::IdentityId, Type::Boolean, Type::IdentityId, Type::Int4]);
141 let mut row = layout.allocate();
142
143 let id1 = IdentityId::generate();
144 let id2 = IdentityId::generate();
145
146 layout.set_identity_id(&mut row, 0, id1.clone());
147 layout.set_bool(&mut row, 1, true);
148 layout.set_identity_id(&mut row, 2, id2.clone());
149 layout.set_i32(&mut row, 3, 42);
150
151 assert_eq!(layout.get_identity_id(&row, 0), id1);
152 assert_eq!(layout.get_bool(&row, 1), true);
153 assert_eq!(layout.get_identity_id(&row, 2), id2);
154 assert_eq!(layout.get_i32(&row, 3), 42);
155 }
156
157 #[test]
158 fn test_undefined_handling() {
159 let layout = EncodedValuesLayout::new(&[Type::IdentityId, Type::IdentityId]);
160 let mut row = layout.allocate();
161
162 let id = IdentityId::generate();
163 layout.set_identity_id(&mut row, 0, id.clone());
164
165 assert_eq!(layout.try_get_identity_id(&row, 0), Some(id));
166 assert_eq!(layout.try_get_identity_id(&row, 1), None);
167
168 layout.set_undefined(&mut row, 0);
169 assert_eq!(layout.try_get_identity_id(&row, 0), None);
170 }
171
172 #[test]
173 fn test_persistence() {
174 let layout = EncodedValuesLayout::new(&[Type::IdentityId]);
175 let mut row = layout.allocate();
176
177 let id = IdentityId::generate();
178 let id_string = id.to_string();
179
180 layout.set_identity_id(&mut row, 0, id.clone());
181 let retrieved = layout.get_identity_id(&row, 0);
182
183 assert_eq!(retrieved, id);
184 assert_eq!(retrieved.to_string(), id_string);
185 assert_eq!(retrieved.as_bytes(), id.as_bytes());
186 }
187
188 #[test]
189 fn test_clone_consistency() {
190 let layout = EncodedValuesLayout::new(&[Type::IdentityId]);
191 let mut row = layout.allocate();
192
193 let original_id = IdentityId::generate();
194 layout.set_identity_id(&mut row, 0, original_id.clone());
195
196 let retrieved_id = layout.get_identity_id(&row, 0);
197 assert_eq!(retrieved_id, original_id);
198
199 assert_eq!(retrieved_id.as_bytes(), original_id.as_bytes());
202 }
203
204 #[test]
205 fn test_multiple_fields() {
206 let layout = EncodedValuesLayout::new(&[Type::IdentityId, Type::IdentityId, Type::IdentityId]);
207 let mut row = layout.allocate();
208
209 let id1 = IdentityId::generate();
210 let id2 = IdentityId::generate();
211 let id3 = IdentityId::generate();
212
213 layout.set_identity_id(&mut row, 0, id1.clone());
214 layout.set_identity_id(&mut row, 1, id2.clone());
215 layout.set_identity_id(&mut row, 2, id3.clone());
216
217 assert_eq!(layout.get_identity_id(&row, 0), id1);
218 assert_eq!(layout.get_identity_id(&row, 1), id2);
219 assert_eq!(layout.get_identity_id(&row, 2), id3);
220
221 assert_ne!(id1, id2);
223 assert_ne!(id1, id3);
224 assert_ne!(id2, id3);
225 }
226
227 #[test]
228 fn test_format_consistency() {
229 let layout = EncodedValuesLayout::new(&[Type::IdentityId]);
230 let mut row = layout.allocate();
231
232 let id = IdentityId::generate();
233 let original_string = id.to_string();
234
235 layout.set_identity_id(&mut row, 0, id.clone());
236 let retrieved = layout.get_identity_id(&row, 0);
237 let retrieved_string = retrieved.to_string();
238
239 assert_eq!(original_string, retrieved_string);
240
241 assert_eq!(original_string.len(), 36);
244 assert_eq!(original_string.matches('-').count(), 4);
245 }
246
247 #[test]
248 fn test_byte_level_storage() {
249 let layout = EncodedValuesLayout::new(&[Type::IdentityId]);
250 let mut row = layout.allocate();
251
252 let id = IdentityId::generate();
253 let original_bytes = *id.as_bytes();
254
255 layout.set_identity_id(&mut row, 0, id.clone());
256 let retrieved = layout.get_identity_id(&row, 0);
257 let retrieved_bytes = *retrieved.as_bytes();
258
259 assert_eq!(original_bytes, retrieved_bytes);
260
261 assert_eq!(original_bytes.len(), 16);
263 assert_eq!(retrieved_bytes.len(), 16);
264 }
265
266 #[test]
267 fn test_time_based_properties() {
268 let layout = EncodedValuesLayout::new(&[Type::IdentityId]);
269
270 let id1 = IdentityId::generate();
272 std::thread::sleep(std::time::Duration::from_millis(2));
273 let id2 = IdentityId::generate();
274
275 let mut row1 = layout.allocate();
276 let mut row2 = layout.allocate();
277
278 layout.set_identity_id(&mut row1, 0, id1.clone());
279 layout.set_identity_id(&mut row2, 0, id2.clone());
280
281 let retrieved1 = layout.get_identity_id(&row1, 0);
282 let retrieved2 = layout.get_identity_id(&row2, 0);
283
284 assert!(retrieved2.as_bytes() > retrieved1.as_bytes());
287 }
288
289 #[test]
290 fn test_as_primary_key() {
291 let layout = EncodedValuesLayout::new(&[
292 Type::IdentityId, Type::Utf8, Type::Int4, ]);
296 let mut row = layout.allocate();
297
298 let primary_key = IdentityId::generate();
300 layout.set_identity_id(&mut row, 0, primary_key.clone());
301 layout.set_utf8(&mut row, 1, "John Doe");
302 layout.set_i32(&mut row, 2, 30);
303
304 assert_eq!(layout.get_identity_id(&row, 0), primary_key);
305 assert_eq!(layout.get_utf8(&row, 1), "John Doe");
306 assert_eq!(layout.get_i32(&row, 2), 30);
307
308 assert_eq!(primary_key.get_version_num(), 7);
310 }
311}