Skip to main content

reifydb_type/value/identity/
mod.rs

1// SPDX-License-Identifier: MIT
2// Copyright (c) 2025 ReifyDB
3
4use std::{fmt, ops::Deref, str::FromStr};
5
6use serde::{Deserialize, Deserializer, Serialize, Serializer, de, de::Visitor};
7use uuid::Uuid;
8
9use crate::value::uuid::Uuid7;
10
11/// An identity identifier - a unique UUID v7 for an identity
12#[repr(transparent)]
13#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Hash, Default)]
14pub struct IdentityId(pub Uuid7);
15
16impl IdentityId {
17	/// Create a new IdentityId with a generated UUID v7
18	pub fn generate() -> Self {
19		IdentityId(Uuid7::generate())
20	}
21
22	/// Create a new IdentityId from an existing Uuid7
23	pub fn new(id: Uuid7) -> Self {
24		IdentityId(id)
25	}
26
27	/// Get the inner Uuid7 value
28	pub fn value(&self) -> Uuid7 {
29		self.0
30	}
31
32	/// Sentinel for anonymous identity: minimum valid UUID v7
33	/// `00000000-0000-7000-8000-000000000000`
34	pub fn anonymous() -> Self {
35		let bytes = [
36			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37		];
38		IdentityId(Uuid7(Uuid::from_bytes(bytes)))
39	}
40
41	/// Sentinel for root identity: maximum valid UUID v7
42	/// `ffffffff-ffff-7fff-bfff-ffffffffffff`
43	pub fn root() -> Self {
44		let bytes = [
45			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
46		];
47		IdentityId(Uuid7(Uuid::from_bytes(bytes)))
48	}
49
50	/// Sentinel for system identity: used for internal engine-initiated operations.
51	/// `ffffffff-fffe-7fff-bfff-ffffffffffff`
52	pub fn system() -> Self {
53		let bytes = [
54			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
55		];
56		IdentityId(Uuid7(Uuid::from_bytes(bytes)))
57	}
58
59	pub fn is_anonymous(&self) -> bool {
60		*self == Self::anonymous()
61	}
62
63	pub fn is_root(&self) -> bool {
64		*self == Self::root()
65	}
66
67	pub fn is_system(&self) -> bool {
68		*self == Self::system()
69	}
70
71	/// Returns true for any privileged identity that bypasses policy enforcement.
72	pub fn is_privileged(&self) -> bool {
73		self.is_root() || self.is_system()
74	}
75}
76
77impl Deref for IdentityId {
78	type Target = Uuid7;
79
80	fn deref(&self) -> &Self::Target {
81		&self.0
82	}
83}
84
85impl PartialEq<Uuid7> for IdentityId {
86	fn eq(&self, other: &Uuid7) -> bool {
87		self.0.eq(other)
88	}
89}
90
91impl From<Uuid7> for IdentityId {
92	fn from(id: Uuid7) -> Self {
93		IdentityId(id)
94	}
95}
96
97impl From<IdentityId> for Uuid7 {
98	fn from(identity_id: IdentityId) -> Self {
99		identity_id.0
100	}
101}
102
103impl fmt::Display for IdentityId {
104	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105		write!(f, "{}", self.0)
106	}
107}
108
109impl Serialize for IdentityId {
110	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
111	where
112		S: Serializer,
113	{
114		self.0.serialize(serializer)
115	}
116}
117
118impl<'de> Deserialize<'de> for IdentityId {
119	fn deserialize<D>(deserializer: D) -> Result<IdentityId, D::Error>
120	where
121		D: Deserializer<'de>,
122	{
123		struct Uuid7Visitor;
124
125		impl<'de> Visitor<'de> for Uuid7Visitor {
126			type Value = IdentityId;
127
128			fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
129				formatter.write_str("a UUID version 7")
130			}
131
132			fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
133			where
134				E: de::Error,
135			{
136				let uuid =
137					Uuid::from_str(value).map_err(|e| E::custom(format!("invalid UUID: {}", e)))?;
138
139				if uuid.get_version_num() != 7 {
140					return Err(E::custom(format!(
141						"expected UUID v7, got v{}",
142						uuid.get_version_num()
143					)));
144				}
145
146				Ok(IdentityId(Uuid7::from(uuid)))
147			}
148
149			fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
150			where
151				E: de::Error,
152			{
153				let uuid = Uuid::from_slice(value)
154					.map_err(|e| E::custom(format!("invalid UUID bytes: {}", e)))?;
155
156				// Verify it's a v7 UUID or nil
157				if uuid.get_version_num() != 7 {
158					return Err(E::custom(format!(
159						"expected UUID v7, got v{}",
160						uuid.get_version_num()
161					)));
162				}
163
164				Ok(IdentityId(Uuid7::from(uuid)))
165			}
166		}
167
168		deserializer.deserialize_any(Uuid7Visitor)
169	}
170}
171
172#[cfg(test)]
173pub mod tests {
174	use super::*;
175
176	#[test]
177	fn test_identity_id_creation() {
178		let id = IdentityId::generate();
179		assert_ne!(id, IdentityId::default());
180	}
181
182	#[test]
183	fn test_identity_id_from_uuid7() {
184		let uuid = Uuid7::generate();
185		let id = IdentityId::from(uuid);
186		assert_eq!(id.value(), uuid);
187	}
188
189	#[test]
190	fn test_identity_id_display() {
191		let id = IdentityId::generate();
192		let display = format!("{}", id);
193		assert!(!display.is_empty());
194	}
195
196	#[test]
197	fn test_identity_id_equality() {
198		let uuid = Uuid7::generate();
199		let id1 = IdentityId::from(uuid);
200		let id2 = IdentityId::from(uuid);
201		assert_eq!(id1, id2);
202	}
203}