reifydb_type/value/identity/
mod.rs

1// Copyright (c) reifydb.com 2025
2// This file is licensed under the MIT, see license.md file
3
4use std::{fmt, ops::Deref};
5
6use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Visitor};
7
8use crate::Uuid7;
9
10/// An identity identifier - a unique UUID v7 for an identity
11#[repr(transparent)]
12#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Hash, Default)]
13pub struct IdentityId(pub Uuid7);
14
15impl IdentityId {
16	/// Create a new IdentityId with a generated UUID v7
17	pub fn generate() -> Self {
18		IdentityId(Uuid7::generate())
19	}
20
21	/// Create a new IdentityId from an existing Uuid7
22	pub fn new(id: Uuid7) -> Self {
23		IdentityId(id)
24	}
25
26	/// Get the inner Uuid7 value
27	pub fn value(&self) -> Uuid7 {
28		self.0
29	}
30}
31
32impl Deref for IdentityId {
33	type Target = Uuid7;
34
35	fn deref(&self) -> &Self::Target {
36		&self.0
37	}
38}
39
40impl PartialEq<Uuid7> for IdentityId {
41	fn eq(&self, other: &Uuid7) -> bool {
42		self.0.eq(other)
43	}
44}
45
46impl From<Uuid7> for IdentityId {
47	fn from(id: Uuid7) -> Self {
48		IdentityId(id)
49	}
50}
51
52impl From<IdentityId> for Uuid7 {
53	fn from(identity_id: IdentityId) -> Self {
54		identity_id.0
55	}
56}
57
58impl fmt::Display for IdentityId {
59	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60		write!(f, "{}", self.0)
61	}
62}
63
64impl Serialize for IdentityId {
65	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
66	where
67		S: Serializer,
68	{
69		self.0.serialize(serializer)
70	}
71}
72
73impl<'de> Deserialize<'de> for IdentityId {
74	fn deserialize<D>(deserializer: D) -> Result<IdentityId, D::Error>
75	where
76		D: Deserializer<'de>,
77	{
78		struct Uuid7Visitor;
79
80		impl<'de> Visitor<'de> for Uuid7Visitor {
81			type Value = IdentityId;
82
83			fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
84				formatter.write_str("a UUID version 7")
85			}
86
87			fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
88			where
89				E: serde::de::Error,
90			{
91				use std::str::FromStr;
92				let uuid = uuid::Uuid::from_str(value)
93					.map_err(|e| E::custom(format!("invalid UUID: {}", e)))?;
94
95				if uuid.get_version_num() != 7 {
96					return Err(E::custom(format!(
97						"expected UUID v7, got v{}",
98						uuid.get_version_num()
99					)));
100				}
101
102				Ok(IdentityId(Uuid7::from(uuid)))
103			}
104
105			fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
106			where
107				E: serde::de::Error,
108			{
109				let uuid = uuid::Uuid::from_slice(value)
110					.map_err(|e| E::custom(format!("invalid UUID bytes: {}", e)))?;
111
112				// Verify it's a v7 UUID or nil
113				if uuid.get_version_num() != 7 {
114					return Err(E::custom(format!(
115						"expected UUID v7, got v{}",
116						uuid.get_version_num()
117					)));
118				}
119
120				Ok(IdentityId(Uuid7::from(uuid)))
121			}
122		}
123
124		deserializer.deserialize_any(Uuid7Visitor)
125	}
126}
127
128#[cfg(test)]
129mod tests {
130	use super::*;
131
132	#[test]
133	fn test_identity_id_creation() {
134		let id = IdentityId::generate();
135		assert_ne!(id, IdentityId::default());
136	}
137
138	#[test]
139	fn test_identity_id_from_uuid7() {
140		let uuid = Uuid7::generate();
141		let id = IdentityId::from(uuid);
142		assert_eq!(id.value(), uuid);
143	}
144
145	#[test]
146	fn test_identity_id_display() {
147		let id = IdentityId::generate();
148		let display = format!("{}", id);
149		assert!(!display.is_empty());
150	}
151
152	#[test]
153	fn test_identity_id_equality() {
154		let uuid = Uuid7::generate();
155		let id1 = IdentityId::from(uuid);
156		let id2 = IdentityId::from(uuid);
157		assert_eq!(id1, id2);
158	}
159}