reifydb_value/value/uuid/
mod.rs1use 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 =
93 u64::try_from(clock.now().to_millis()).expect("system clock is never before the Unix epoch");
94 let random_bytes = rng.bytes_10();
95 Uuid7(Builder::from_unix_timestamp_millis(millis, &random_bytes).into_uuid())
96 }
97}
98
99impl Deref for Uuid7 {
100 type Target = StdUuid;
101
102 fn deref(&self) -> &Self::Target {
103 &self.0
104 }
105}
106
107impl PartialOrd for Uuid7 {
108 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
109 Some(self.cmp(other))
110 }
111}
112
113impl Ord for Uuid7 {
114 fn cmp(&self, other: &Self) -> Ordering {
115 self.0.as_bytes().cmp(other.0.as_bytes())
116 }
117}
118
119impl From<StdUuid> for Uuid7 {
120 fn from(uuid: StdUuid) -> Self {
121 reifydb_assertions! {
122 assert!(uuid.get_version_num() == 7 || uuid.get_version_num() == 0);
123 }
124 Uuid7(uuid)
125 }
126}
127
128impl From<Uuid7> for StdUuid {
129 fn from(uuid7: Uuid7) -> Self {
130 uuid7.0
131 }
132}
133
134impl Display for Uuid7 {
135 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
136 write!(f, "{}", self.0)
137 }
138}
139
140#[cfg(test)]
141#[allow(clippy::approx_constant)]
142pub mod tests {
143 use super::*;
144 use crate::clock::testing::{TestClock, TestRng};
145
146 fn test_clock_and_rng() -> (TestClock, TestClock, TestRng) {
147 let clock = TestClock::from_millis(1000);
148 (clock.clone(), clock, TestRng)
149 }
150
151 #[cfg(feature = "host")]
152 #[test]
153 fn test_uuid4_generate() {
154 let uuid4 = Uuid4::generate();
155 assert_eq!(uuid4.get_version_num(), 4);
156 }
157
158 #[cfg(feature = "host")]
159 #[test]
160 fn test_uuid4_equality() {
161 let std_uuid = StdUuid::new_v4();
162 let uuid4_a = Uuid4(std_uuid);
163 let uuid4_b = Uuid4(std_uuid);
164 let uuid4_c = Uuid4::generate();
165
166 assert_eq!(uuid4_a, uuid4_b);
167 assert_ne!(uuid4_a, uuid4_c);
168 }
169
170 #[cfg(feature = "host")]
171 #[test]
172 fn test_uuid4_ordering() {
173 let uuid4_a = Uuid4::generate();
174 let uuid4_b = Uuid4::generate();
175
176 let cmp1 = uuid4_a.cmp(&uuid4_b);
177 let cmp2 = uuid4_a.cmp(&uuid4_b);
178 assert_eq!(cmp1, cmp2);
179
180 assert_eq!(uuid4_a.cmp(&uuid4_a), Ordering::Equal);
181 }
182
183 #[cfg(feature = "host")]
184 #[test]
185 fn test_uuid4_display() {
186 let std_uuid = StdUuid::new_v4();
187 let uuid4 = Uuid4(std_uuid);
188
189 assert_eq!(format!("{}", uuid4), format!("{}", std_uuid));
190 }
191
192 #[test]
193 fn test_uuid7_generate() {
194 let (_, clock, rng) = test_clock_and_rng();
195 let uuid7 = Uuid7::generate(&clock, &rng);
196 assert_eq!(uuid7.get_version_num(), 7);
197 }
198
199 #[test]
200 fn test_uuid7_equality() {
201 let (mock, clock, rng) = test_clock_and_rng();
202 let uuid7_a = Uuid7::generate(&clock, &rng);
203 let uuid7_b = Uuid7(uuid7_a.0);
204 mock.advance_millis(1);
205 let uuid7_c = Uuid7::generate(&clock, &rng);
206
207 assert_eq!(uuid7_a, uuid7_b);
208 assert_ne!(uuid7_a, uuid7_c);
209 }
210
211 #[test]
212 fn test_uuid7_ordering() {
213 let (mock, clock, rng) = test_clock_and_rng();
214 let uuid7_a = Uuid7::generate(&clock, &rng);
215 mock.advance_millis(1);
216 let uuid7_b = Uuid7::generate(&clock, &rng);
217
218 let cmp1 = uuid7_a.cmp(&uuid7_b);
219 let cmp2 = uuid7_a.cmp(&uuid7_b);
220 assert_eq!(cmp1, cmp2);
221
222 assert_eq!(uuid7_a.cmp(&uuid7_a), Ordering::Equal);
223 }
224
225 #[test]
226 fn test_uuid7_display() {
227 let (_, clock, rng) = test_clock_and_rng();
228 let uuid7 = Uuid7::generate(&clock, &rng);
229 let display = format!("{}", uuid7);
230 assert!(!display.is_empty());
231 }
232
233 #[test]
234 fn test_uuid7_timestamp_ordering() {
235 let (mock, clock, rng) = test_clock_and_rng();
236 let uuid7_first = Uuid7::generate(&clock, &rng);
237 mock.advance_millis(1);
238 let uuid7_second = Uuid7::generate(&clock, &rng);
239
240 assert!(uuid7_first < uuid7_second);
241 }
242}