Skip to main content

reifydb_value/value/uuid/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4use std::{
5	cmp::Ordering,
6	fmt,
7	fmt::{Display, Formatter},
8	ops::Deref,
9};
10
11use ::uuid::{Builder, Uuid as StdUuid};
12use serde::{Deserialize, Serialize};
13use uuid::Uuid;
14
15use crate::{
16	clock::{ClockNow, RandomBytes},
17	reifydb_assertions,
18};
19
20pub mod parse;
21
22#[repr(transparent)]
23#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
24pub struct Uuid4(pub StdUuid);
25
26impl Uuid4 {
27	pub fn generate() -> Self {
28		Uuid4(StdUuid::new_v4())
29	}
30}
31
32impl Default for Uuid4 {
33	fn default() -> Self {
34		Self(Uuid::nil())
35	}
36}
37
38impl Deref for Uuid4 {
39	type Target = StdUuid;
40
41	fn deref(&self) -> &Self::Target {
42		&self.0
43	}
44}
45
46impl PartialOrd for Uuid4 {
47	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
48		Some(self.cmp(other))
49	}
50}
51
52impl Ord for Uuid4 {
53	fn cmp(&self, other: &Self) -> Ordering {
54		self.0.as_bytes().cmp(other.0.as_bytes())
55	}
56}
57
58impl From<StdUuid> for Uuid4 {
59	fn from(uuid: StdUuid) -> Self {
60		reifydb_assertions! {
61			assert!(uuid.get_version_num() == 4 || uuid.get_version_num() == 0);
62		}
63		Uuid4(uuid)
64	}
65}
66
67impl From<Uuid4> for StdUuid {
68	fn from(uuid4: Uuid4) -> Self {
69		uuid4.0
70	}
71}
72
73impl Display for Uuid4 {
74	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
75		write!(f, "{}", self.0)
76	}
77}
78
79#[repr(transparent)]
80#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
81pub struct Uuid7(pub StdUuid);
82
83impl Default for Uuid7 {
84	fn default() -> Self {
85		Self(Uuid::nil())
86	}
87}
88
89impl Uuid7 {
90	pub fn generate<C: ClockNow, R: RandomBytes>(clock: &C, rng: &R) -> Self {
91		let millis = clock.now_millis();
92		let random_bytes = rng.bytes_10();
93		Uuid7(Builder::from_unix_timestamp_millis(millis, &random_bytes).into_uuid())
94	}
95}
96
97impl Deref for Uuid7 {
98	type Target = StdUuid;
99
100	fn deref(&self) -> &Self::Target {
101		&self.0
102	}
103}
104
105impl PartialOrd for Uuid7 {
106	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
107		Some(self.cmp(other))
108	}
109}
110
111impl Ord for Uuid7 {
112	fn cmp(&self, other: &Self) -> Ordering {
113		self.0.as_bytes().cmp(other.0.as_bytes())
114	}
115}
116
117impl From<StdUuid> for Uuid7 {
118	fn from(uuid: StdUuid) -> Self {
119		reifydb_assertions! {
120			assert!(uuid.get_version_num() == 7 || uuid.get_version_num() == 0);
121		}
122		Uuid7(uuid)
123	}
124}
125
126impl From<Uuid7> for StdUuid {
127	fn from(uuid7: Uuid7) -> Self {
128		uuid7.0
129	}
130}
131
132impl Display for Uuid7 {
133	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
134		write!(f, "{}", self.0)
135	}
136}
137
138#[cfg(test)]
139#[allow(clippy::approx_constant)]
140pub mod tests {
141	use super::*;
142	use crate::clock::testing::{TestClock, TestRng};
143
144	fn test_clock_and_rng() -> (TestClock, TestClock, TestRng) {
145		let clock = TestClock::from_millis(1000);
146		(clock.clone(), clock, TestRng)
147	}
148
149	#[test]
150	fn test_uuid4_generate() {
151		let uuid4 = Uuid4::generate();
152		assert_eq!(uuid4.get_version_num(), 4);
153	}
154
155	#[test]
156	fn test_uuid4_equality() {
157		let std_uuid = StdUuid::new_v4();
158		let uuid4_a = Uuid4(std_uuid);
159		let uuid4_b = Uuid4(std_uuid);
160		let uuid4_c = Uuid4::generate();
161
162		assert_eq!(uuid4_a, uuid4_b);
163		assert_ne!(uuid4_a, uuid4_c);
164	}
165
166	#[test]
167	fn test_uuid4_ordering() {
168		let uuid4_a = Uuid4::generate();
169		let uuid4_b = Uuid4::generate();
170
171		let cmp1 = uuid4_a.cmp(&uuid4_b);
172		let cmp2 = uuid4_a.cmp(&uuid4_b);
173		assert_eq!(cmp1, cmp2);
174
175		assert_eq!(uuid4_a.cmp(&uuid4_a), Ordering::Equal);
176	}
177
178	#[test]
179	fn test_uuid4_display() {
180		let std_uuid = StdUuid::new_v4();
181		let uuid4 = Uuid4(std_uuid);
182
183		assert_eq!(format!("{}", uuid4), format!("{}", std_uuid));
184	}
185
186	#[test]
187	fn test_uuid7_generate() {
188		let (_, clock, rng) = test_clock_and_rng();
189		let uuid7 = Uuid7::generate(&clock, &rng);
190		assert_eq!(uuid7.get_version_num(), 7);
191	}
192
193	#[test]
194	fn test_uuid7_equality() {
195		let (mock, clock, rng) = test_clock_and_rng();
196		let uuid7_a = Uuid7::generate(&clock, &rng);
197		let uuid7_b = Uuid7(uuid7_a.0);
198		mock.advance_millis(1);
199		let uuid7_c = Uuid7::generate(&clock, &rng);
200
201		assert_eq!(uuid7_a, uuid7_b);
202		assert_ne!(uuid7_a, uuid7_c);
203	}
204
205	#[test]
206	fn test_uuid7_ordering() {
207		let (mock, clock, rng) = test_clock_and_rng();
208		let uuid7_a = Uuid7::generate(&clock, &rng);
209		mock.advance_millis(1);
210		let uuid7_b = Uuid7::generate(&clock, &rng);
211
212		let cmp1 = uuid7_a.cmp(&uuid7_b);
213		let cmp2 = uuid7_a.cmp(&uuid7_b);
214		assert_eq!(cmp1, cmp2);
215
216		assert_eq!(uuid7_a.cmp(&uuid7_a), Ordering::Equal);
217	}
218
219	#[test]
220	fn test_uuid7_display() {
221		let (_, clock, rng) = test_clock_and_rng();
222		let uuid7 = Uuid7::generate(&clock, &rng);
223		let display = format!("{}", uuid7);
224		assert!(!display.is_empty());
225	}
226
227	#[test]
228	fn test_uuid7_timestamp_ordering() {
229		let (mock, clock, rng) = test_clock_and_rng();
230		let uuid7_first = Uuid7::generate(&clock, &rng);
231		mock.advance_millis(1);
232		let uuid7_second = Uuid7::generate(&clock, &rng);
233
234		assert!(uuid7_first < uuid7_second);
235	}
236}