Skip to main content

reifydb_value/value/uuid/
mod.rs

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