Skip to main content

reifydb_codec/encoded/
uuid4.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4use std::ptr;
5
6use reifydb_value::{
7	reifydb_assertions,
8	value::{uuid::Uuid4, value_type::ValueType},
9};
10use uuid::Uuid;
11
12use crate::encoded::{row::EncodedRow, shape::RowShape};
13
14impl RowShape {
15	pub fn set_uuid4(&self, row: &mut EncodedRow, index: usize, value: Uuid4) {
16		let field = &self.fields()[index];
17		reifydb_assertions! {
18			assert!(
19				row.len() >= self.total_static_size(),
20				"row/shape size mismatch: row.len()={} < total_static_size()={}",
21				row.len(),
22				self.total_static_size()
23			);
24			assert_eq!(*field.constraint.get_type().inner_type(), ValueType::Uuid4);
25		}
26		row.set_valid(index, true);
27		unsafe {
28			ptr::write_unaligned(
29				row.make_mut().as_mut_ptr().add(field.offset as usize) as *mut [u8; 16],
30				*value.as_bytes(),
31			);
32		}
33	}
34
35	pub fn get_uuid4(&self, row: &EncodedRow, index: usize) -> Uuid4 {
36		let field = &self.fields()[index];
37		reifydb_assertions! {
38			assert!(
39				row.len() >= self.total_static_size(),
40				"row/shape size mismatch: row.len()={} < total_static_size()={}",
41				row.len(),
42				self.total_static_size()
43			);
44			assert_eq!(*field.constraint.get_type().inner_type(), ValueType::Uuid4);
45		}
46		unsafe {
47			let bytes: [u8; 16] =
48				ptr::read_unaligned(row.as_ptr().add(field.offset as usize) as *const [u8; 16]);
49			Uuid4::from(Uuid::from_bytes(bytes))
50		}
51	}
52
53	pub fn try_get_uuid4(&self, row: &EncodedRow, index: usize) -> Option<Uuid4> {
54		if row.is_defined(index) && self.fields()[index].constraint.get_type() == ValueType::Uuid4 {
55			Some(self.get_uuid4(row, index))
56		} else {
57			None
58		}
59	}
60}
61
62#[cfg(test)]
63pub mod tests {
64	use reifydb_value::value::{uuid::Uuid4, value_type::ValueType};
65
66	use crate::encoded::shape::RowShape;
67
68	#[test]
69	fn test_set_get_uuid4() {
70		let shape = RowShape::testing(&[ValueType::Uuid4]);
71		let mut row = shape.allocate();
72
73		let uuid = Uuid4::generate();
74		shape.set_uuid4(&mut row, 0, uuid.clone());
75		assert_eq!(shape.get_uuid4(&row, 0), uuid);
76	}
77
78	#[test]
79	fn test_try_get_uuid4() {
80		let shape = RowShape::testing(&[ValueType::Uuid4]);
81		let mut row = shape.allocate();
82
83		assert_eq!(shape.try_get_uuid4(&row, 0), None);
84
85		let uuid = Uuid4::generate();
86		shape.set_uuid4(&mut row, 0, uuid.clone());
87		assert_eq!(shape.try_get_uuid4(&row, 0), Some(uuid));
88	}
89
90	#[test]
91	fn test_multiple_generations() {
92		let shape = RowShape::testing(&[ValueType::Uuid4]);
93
94		// Generate multiple UUIDs and ensure they're different
95		let mut uuids = Vec::new();
96		for _ in 0..10 {
97			let mut row = shape.allocate();
98			let uuid = Uuid4::generate();
99			shape.set_uuid4(&mut row, 0, uuid.clone());
100			let retrieved = shape.get_uuid4(&row, 0);
101			assert_eq!(retrieved, uuid);
102			uuids.push(uuid);
103		}
104
105		// Ensure all generated UUIDs are unique
106		for i in 0..uuids.len() {
107			for j in (i + 1)..uuids.len() {
108				assert_ne!(uuids[i], uuids[j], "UUIDs should be unique");
109			}
110		}
111	}
112
113	#[test]
114	fn test_version_check() {
115		let shape = RowShape::testing(&[ValueType::Uuid4]);
116		let mut row = shape.allocate();
117
118		let uuid = Uuid4::generate();
119		shape.set_uuid4(&mut row, 0, uuid.clone());
120		let retrieved = shape.get_uuid4(&row, 0);
121
122		// Verify it's a version 4 UUID
123		assert_eq!(retrieved.get_version_num(), 4);
124	}
125
126	#[test]
127	fn test_mixed_with_other_types() {
128		let shape =
129			RowShape::testing(&[ValueType::Uuid4, ValueType::Boolean, ValueType::Uuid4, ValueType::Int4]);
130		let mut row = shape.allocate();
131
132		let uuid1 = Uuid4::generate();
133		let uuid2 = Uuid4::generate();
134
135		shape.set_uuid4(&mut row, 0, uuid1.clone());
136		shape.set_bool(&mut row, 1, true);
137		shape.set_uuid4(&mut row, 2, uuid2.clone());
138		shape.set_i32(&mut row, 3, 42);
139
140		assert_eq!(shape.get_uuid4(&row, 0), uuid1);
141		assert_eq!(shape.get_bool(&row, 1), true);
142		assert_eq!(shape.get_uuid4(&row, 2), uuid2);
143		assert_eq!(shape.get_i32(&row, 3), 42);
144	}
145
146	#[test]
147	fn test_undefined_handling() {
148		let shape = RowShape::testing(&[ValueType::Uuid4, ValueType::Uuid4]);
149		let mut row = shape.allocate();
150
151		let uuid = Uuid4::generate();
152		shape.set_uuid4(&mut row, 0, uuid.clone());
153
154		assert_eq!(shape.try_get_uuid4(&row, 0), Some(uuid));
155		assert_eq!(shape.try_get_uuid4(&row, 1), None);
156
157		shape.set_none(&mut row, 0);
158		assert_eq!(shape.try_get_uuid4(&row, 0), None);
159	}
160
161	#[test]
162	fn test_persistence() {
163		let shape = RowShape::testing(&[ValueType::Uuid4]);
164		let mut row = shape.allocate();
165
166		let uuid = Uuid4::generate();
167		let uuid_string = uuid.to_string();
168
169		shape.set_uuid4(&mut row, 0, uuid.clone());
170		let retrieved = shape.get_uuid4(&row, 0);
171
172		assert_eq!(retrieved, uuid);
173		assert_eq!(retrieved.to_string(), uuid_string);
174		assert_eq!(retrieved.as_bytes(), uuid.as_bytes());
175	}
176
177	#[test]
178	fn test_clone_consistency() {
179		let shape = RowShape::testing(&[ValueType::Uuid4]);
180		let mut row = shape.allocate();
181
182		let original_uuid = Uuid4::generate();
183		shape.set_uuid4(&mut row, 0, original_uuid.clone());
184
185		let retrieved_uuid = shape.get_uuid4(&row, 0);
186		assert_eq!(retrieved_uuid, original_uuid);
187
188		// Verify that the byte representation is identical
189		assert_eq!(retrieved_uuid.as_bytes(), original_uuid.as_bytes());
190	}
191
192	#[test]
193	fn test_multiple_fields() {
194		let shape = RowShape::testing(&[ValueType::Uuid4, ValueType::Uuid4, ValueType::Uuid4]);
195		let mut row = shape.allocate();
196
197		let uuid1 = Uuid4::generate();
198		let uuid2 = Uuid4::generate();
199		let uuid3 = Uuid4::generate();
200
201		shape.set_uuid4(&mut row, 0, uuid1.clone());
202		shape.set_uuid4(&mut row, 1, uuid2.clone());
203		shape.set_uuid4(&mut row, 2, uuid3.clone());
204
205		assert_eq!(shape.get_uuid4(&row, 0), uuid1);
206		assert_eq!(shape.get_uuid4(&row, 1), uuid2);
207		assert_eq!(shape.get_uuid4(&row, 2), uuid3);
208
209		// Ensure all UUIDs are different
210		assert_ne!(uuid1, uuid2);
211		assert_ne!(uuid1, uuid3);
212		assert_ne!(uuid2, uuid3);
213	}
214
215	#[test]
216	fn test_format_consistency() {
217		let shape = RowShape::testing(&[ValueType::Uuid4]);
218		let mut row = shape.allocate();
219
220		let uuid = Uuid4::generate();
221		let original_string = uuid.to_string();
222
223		shape.set_uuid4(&mut row, 0, uuid.clone());
224		let retrieved = shape.get_uuid4(&row, 0);
225		let retrieved_string = retrieved.to_string();
226
227		assert_eq!(original_string, retrieved_string);
228
229		// Verify UUID string format (8-4-4-4-12)
230		assert_eq!(original_string.len(), 36);
231		assert_eq!(original_string.matches('-').count(), 4);
232	}
233
234	#[test]
235	fn test_byte_level_storage() {
236		let shape = RowShape::testing(&[ValueType::Uuid4]);
237		let mut row = shape.allocate();
238
239		let uuid = Uuid4::generate();
240		let original_bytes = *uuid.as_bytes();
241
242		shape.set_uuid4(&mut row, 0, uuid.clone());
243		let retrieved = shape.get_uuid4(&row, 0);
244		let retrieved_bytes = *retrieved.as_bytes();
245
246		assert_eq!(original_bytes, retrieved_bytes);
247
248		// Verify that it's exactly 16 bytes
249		assert_eq!(original_bytes.len(), 16);
250		assert_eq!(retrieved_bytes.len(), 16);
251	}
252
253	#[test]
254	fn test_try_get_uuid4_wrong_type() {
255		let shape = RowShape::testing(&[ValueType::Boolean]);
256		let mut row = shape.allocate();
257
258		shape.set_bool(&mut row, 0, true);
259
260		assert_eq!(shape.try_get_uuid4(&row, 0), None);
261	}
262}