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