reifydb_value/value/identity/
mod.rs1use std::{fmt, ops::Deref, str::FromStr};
5
6use serde::{Deserialize, Deserializer, Serialize, Serializer, de, de::Visitor};
7use uuid::Uuid;
8
9use crate::{
10 clock::{ClockNow, RandomBytes},
11 value::uuid::Uuid7,
12};
13
14#[repr(transparent)]
15#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Hash, Default)]
16pub struct IdentityId(pub Uuid7);
17
18impl IdentityId {
19 pub fn generate<C: ClockNow, R: RandomBytes>(clock: &C, rng: &R) -> Self {
20 IdentityId(Uuid7::generate(clock, rng))
21 }
22
23 pub fn new(id: Uuid7) -> Self {
24 IdentityId(id)
25 }
26
27 pub fn value(&self) -> Uuid7 {
28 self.0
29 }
30
31 pub fn anonymous() -> Self {
32 let bytes = [
33 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34 ];
35 IdentityId(Uuid7(Uuid::from_bytes(bytes)))
36 }
37
38 pub fn root() -> Self {
39 let bytes = [
40 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
41 ];
42 IdentityId(Uuid7(Uuid::from_bytes(bytes)))
43 }
44
45 pub fn system() -> Self {
46 let bytes = [
47 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
48 ];
49 IdentityId(Uuid7(Uuid::from_bytes(bytes)))
50 }
51
52 pub fn is_anonymous(&self) -> bool {
53 *self == Self::anonymous()
54 }
55
56 pub fn is_root(&self) -> bool {
57 *self == Self::root()
58 }
59
60 pub fn is_system(&self) -> bool {
61 *self == Self::system()
62 }
63
64 pub fn is_privileged(&self) -> bool {
65 self.is_root() || self.is_system()
66 }
67}
68
69impl Deref for IdentityId {
70 type Target = Uuid7;
71
72 fn deref(&self) -> &Self::Target {
73 &self.0
74 }
75}
76
77impl PartialEq<Uuid7> for IdentityId {
78 fn eq(&self, other: &Uuid7) -> bool {
79 self.0.eq(other)
80 }
81}
82
83impl From<Uuid7> for IdentityId {
84 fn from(id: Uuid7) -> Self {
85 IdentityId(id)
86 }
87}
88
89impl From<IdentityId> for Uuid7 {
90 fn from(identity_id: IdentityId) -> Self {
91 identity_id.0
92 }
93}
94
95impl fmt::Display for IdentityId {
96 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97 write!(f, "{}", self.0)
98 }
99}
100
101impl Serialize for IdentityId {
102 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
103 where
104 S: Serializer,
105 {
106 Serialize::serialize(&self.0, serializer)
107 }
108}
109
110impl<'de> Deserialize<'de> for IdentityId {
111 fn deserialize<D>(deserializer: D) -> Result<IdentityId, D::Error>
112 where
113 D: Deserializer<'de>,
114 {
115 struct Uuid7Visitor;
116
117 impl<'de> Visitor<'de> for Uuid7Visitor {
118 type Value = IdentityId;
119
120 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
121 formatter.write_str("a UUID version 7")
122 }
123
124 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
125 where
126 E: de::Error,
127 {
128 let uuid =
129 Uuid::from_str(value).map_err(|e| E::custom(format!("invalid UUID: {}", e)))?;
130
131 if uuid.get_version_num() != 7 {
132 return Err(E::custom(format!(
133 "expected UUID v7, got v{}",
134 uuid.get_version_num()
135 )));
136 }
137
138 Ok(IdentityId(Uuid7::from(uuid)))
139 }
140
141 fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
142 where
143 E: de::Error,
144 {
145 let uuid = Uuid::from_slice(value)
146 .map_err(|e| E::custom(format!("invalid UUID bytes: {}", e)))?;
147
148 if uuid.get_version_num() != 7 {
149 return Err(E::custom(format!(
150 "expected UUID v7, got v{}",
151 uuid.get_version_num()
152 )));
153 }
154
155 Ok(IdentityId(Uuid7::from(uuid)))
156 }
157 }
158
159 if deserializer.is_human_readable() {
160 deserializer.deserialize_str(Uuid7Visitor)
161 } else {
162 deserializer.deserialize_bytes(Uuid7Visitor)
163 }
164 }
165}
166
167#[cfg(test)]
168pub mod tests {
169 use postcard::{from_bytes, to_allocvec};
170 use serde_json::{from_str, to_string};
171
172 use super::*;
173 use crate::clock::testing::{TestClock, TestRng};
174
175 fn test_clock_and_rng() -> (TestClock, TestClock, TestRng) {
176 let clock = TestClock::from_millis(1000);
177 (clock.clone(), clock, TestRng)
178 }
179
180 #[test]
181 fn test_identity_id_creation() {
182 let (_, clock, rng) = test_clock_and_rng();
183 let id = IdentityId::generate(&clock, &rng);
184 assert_ne!(id, IdentityId::default());
185 }
186
187 #[test]
188 fn test_identity_id_from_uuid7() {
189 let (_, clock, rng) = test_clock_and_rng();
190 let uuid = Uuid7::generate(&clock, &rng);
191 let id = IdentityId::from(uuid);
192 assert_eq!(id.value(), uuid);
193 }
194
195 #[test]
196 fn test_identity_id_display() {
197 let (_, clock, rng) = test_clock_and_rng();
198 let id = IdentityId::generate(&clock, &rng);
199 let display = format!("{}", id);
200 assert!(!display.is_empty());
201 }
202
203 #[test]
204 fn test_identity_id_equality() {
205 let (_, clock, rng) = test_clock_and_rng();
206 let uuid = Uuid7::generate(&clock, &rng);
207 let id1 = IdentityId::from(uuid);
208 let id2 = IdentityId::from(uuid);
209 assert_eq!(id1, id2);
210 }
211
212 #[test]
213 fn test_identity_id_postcard_roundtrip() {
214 let (_, clock, rng) = test_clock_and_rng();
215 let id = IdentityId::generate(&clock, &rng);
216 let bytes = to_allocvec(&id).expect("postcard serialize");
217 let decoded: IdentityId = from_bytes(&bytes).expect("postcard deserialize");
218 assert_eq!(id, decoded);
219 }
220
221 #[test]
222 fn test_identity_id_postcard_roundtrip_root() {
223 let id = IdentityId::root();
224 let bytes = to_allocvec(&id).expect("postcard serialize root");
225 let decoded: IdentityId = from_bytes(&bytes).expect("postcard deserialize root");
226 assert_eq!(id, decoded);
227 }
228
229 #[test]
230 fn test_identity_id_json_roundtrip() {
231 let (_, clock, rng) = test_clock_and_rng();
232 let id = IdentityId::generate(&clock, &rng);
233 let s = to_string(&id).expect("json serialize");
234 let decoded: IdentityId = from_str(&s).expect("json deserialize");
235 assert_eq!(id, decoded);
236 }
237}