Skip to main content

reifydb_core/encoded/
uuid4.rs

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