Skip to main content

reifydb_value/value/uuid/
parse.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4use ::uuid::Uuid;
5
6use crate::{
7	error::{Error, TypeError},
8	fragment::Fragment,
9	value::{
10		identity::IdentityId,
11		uuid::{Uuid4, Uuid7},
12	},
13};
14
15pub fn parse_uuid4(fragment: Fragment) -> Result<Uuid4, Error> {
16	let value = fragment.text().trim();
17
18	if let Ok(uuid) = Uuid::parse_str(value)
19		&& uuid.get_version_num() == 4
20	{
21		return Ok(Uuid4(uuid));
22	}
23	Err(TypeError::InvalidUuid4Format {
24		fragment,
25	}
26	.into())
27}
28
29pub fn parse_uuid7(fragment: Fragment) -> Result<Uuid7, Error> {
30	let value = fragment.text().trim();
31	if let Ok(uuid) = Uuid::parse_str(value)
32		&& uuid.get_version_num() == 7
33	{
34		return Ok(Uuid7(uuid));
35	}
36
37	Err(TypeError::InvalidUuid7Format {
38		fragment,
39	}
40	.into())
41}
42
43pub fn parse_identity_id(fragment: Fragment) -> Result<IdentityId, Error> {
44	let uuid7 = parse_uuid7(fragment)?;
45	Ok(IdentityId(uuid7))
46}
47
48#[cfg(test)]
49pub mod tests {
50
51	mod uuid4 {
52		use crate::{fragment::Fragment, value::uuid::parse::parse_uuid4};
53
54		#[test]
55		fn test_valid_uuid4() {
56			let uuid_str = "550e8400-e29b-41d4-a716-446655440000";
57			let result = parse_uuid4(Fragment::testing(uuid_str));
58			assert!(result.is_ok());
59			let uuid = result.unwrap();
60			assert_eq!(uuid.get_version_num(), 4);
61		}
62
63		#[test]
64		fn test_valid_uuid4_uppercase() {
65			let uuid_str = "550E8400-E29B-41D4-A716-446655440000";
66			let result = parse_uuid4(Fragment::testing(uuid_str));
67			assert!(result.is_ok());
68			let uuid = result.unwrap();
69			assert_eq!(uuid.get_version_num(), 4);
70		}
71
72		#[test]
73		fn test_valid_uuid4_with_spaces() {
74			let uuid_str = "  550e8400-e29b-41d4-a716-446655440000  ";
75			let result = parse_uuid4(Fragment::testing(uuid_str));
76			assert!(result.is_ok());
77			let uuid = result.unwrap();
78			assert_eq!(uuid.get_version_num(), 4);
79		}
80
81		#[test]
82		fn test_invalid_uuid4_empty() {
83			let result = parse_uuid4(Fragment::testing(""));
84			assert!(result.is_err());
85		}
86
87		#[test]
88		fn test_invalid_uuid4_whitespace() {
89			let result = parse_uuid4(Fragment::testing("   "));
90			assert!(result.is_err());
91		}
92
93		#[test]
94		fn test_invalid_uuid4_format() {
95			let result = parse_uuid4(Fragment::testing("not-a-uuid"));
96			assert!(result.is_err());
97		}
98
99		#[test]
100		fn test_invalid_uuid4_wrong_version() {
101			// Well-formed but v1: parsing must check the version nibble, not just the shape.
102			let uuid_str = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
103			let result = parse_uuid4(Fragment::testing(uuid_str));
104			assert!(result.is_err());
105		}
106
107		#[test]
108		fn test_invalid_uuid4_malformed() {
109			let result = parse_uuid4(Fragment::testing("550e8400-e29b-41d4-a716"));
110			assert!(result.is_err());
111		}
112	}
113
114	mod uuid7 {
115		use crate::{fragment::Fragment, value::uuid::parse::parse_uuid7};
116
117		#[test]
118		fn test_valid_uuid7() {
119			let uuid_str = "017f22e2-79b0-7cc3-98c4-dc0c0c07398f";
120			let result = parse_uuid7(Fragment::testing(uuid_str));
121			assert!(result.is_ok());
122			let uuid = result.unwrap();
123			assert_eq!(uuid.get_version_num(), 7);
124		}
125
126		#[test]
127		fn test_valid_uuid7_uppercase() {
128			let uuid_str = "017F22E2-79B0-7CC3-98C4-DC0C0C07398F";
129			let result = parse_uuid7(Fragment::testing(uuid_str));
130			assert!(result.is_ok());
131			let uuid = result.unwrap();
132			assert_eq!(uuid.get_version_num(), 7);
133		}
134
135		#[test]
136		fn test_valid_uuid7_with_spaces() {
137			let uuid_str = "  017f22e2-79b0-7cc3-98c4-dc0c0c07398f  ";
138			let result = parse_uuid7(Fragment::testing(uuid_str));
139			assert!(result.is_ok());
140			let uuid = result.unwrap();
141			assert_eq!(uuid.get_version_num(), 7);
142		}
143
144		#[test]
145		fn test_invalid_uuid7_empty() {
146			let result = parse_uuid7(Fragment::testing(""));
147			assert!(result.is_err());
148		}
149
150		#[test]
151		fn test_invalid_uuid7_whitespace() {
152			let result = parse_uuid7(Fragment::testing("   "));
153			assert!(result.is_err());
154		}
155
156		#[test]
157		fn test_invalid_uuid7_format() {
158			let result = parse_uuid7(Fragment::testing("invalid-uuid"));
159			assert!(result.is_err());
160		}
161
162		#[test]
163		fn test_invalid_uuid7_wrong_version() {
164			// Well-formed but v4, which has no timestamp and so cannot be a Uuid7.
165			let uuid_str = "550e8400-e29b-41d4-a716-446655440000";
166			let result = parse_uuid7(Fragment::testing(uuid_str));
167			assert!(result.is_err());
168		}
169
170		#[test]
171		fn test_invalid_uuid7_malformed() {
172			let result = parse_uuid7(Fragment::testing("017f22e2-79b0-7cc3"));
173			assert!(result.is_err());
174		}
175	}
176
177	mod identity_id {
178		use crate::{fragment::Fragment, value::uuid::parse::parse_identity_id};
179
180		#[test]
181		fn test_valid_identity_id() {
182			let uuid_str = "017f22e2-79b0-7cc3-98c4-dc0c0c07398f";
183			let result = parse_identity_id(Fragment::testing(uuid_str));
184			assert!(result.is_ok());
185			let id = result.unwrap();
186			assert_eq!(id.0.get_version_num(), 7);
187		}
188
189		#[test]
190		fn test_valid_identity_id_uppercase() {
191			let uuid_str = "017F22E2-79B0-7CC3-98C4-DC0C0C07398F";
192			let result = parse_identity_id(Fragment::testing(uuid_str));
193			assert!(result.is_ok());
194		}
195
196		#[test]
197		fn test_valid_identity_id_with_spaces() {
198			let uuid_str = "  017f22e2-79b0-7cc3-98c4-dc0c0c07398f  ";
199			let result = parse_identity_id(Fragment::testing(uuid_str));
200			assert!(result.is_ok());
201		}
202
203		#[test]
204		fn test_invalid_identity_id_empty() {
205			let result = parse_identity_id(Fragment::testing(""));
206			assert!(result.is_err());
207		}
208
209		#[test]
210		fn test_invalid_identity_id_wrong_version() {
211			// IdentityId is backed by Uuid7, so a v4 must be rejected here too.
212			let uuid_str = "550e8400-e29b-41d4-a716-446655440000";
213			let result = parse_identity_id(Fragment::testing(uuid_str));
214			assert!(result.is_err());
215		}
216
217		#[test]
218		fn test_invalid_identity_id_malformed() {
219			let result = parse_identity_id(Fragment::testing("not-a-uuid"));
220			assert!(result.is_err());
221		}
222	}
223}