Skip to main content

surrealdb_expr/val/
uuid.rs

1use std::fmt::{self, Display, Formatter};
2use std::ops::Deref;
3use std::str;
4use std::str::FromStr;
5
6use common::fmt::QuoteStr;
7use revision::revisioned;
8use storekey::{BorrowDecode, Encode};
9use surrealdb_types::{SqlFormat, ToSql, write_sql};
10
11use super::Datetime;
12use crate::val::IndexFormat;
13
14#[revisioned(revision = 1)]
15#[derive(
16	Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd, Hash, Encode, BorrowDecode,
17)]
18#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
19#[storekey(format = "()")]
20#[storekey(format = "IndexFormat")]
21pub struct Uuid(pub uuid::Uuid);
22
23impl Uuid {
24	/// Generate a new UUID
25	pub fn new() -> Self {
26		Self(uuid::Uuid::now_v7())
27	}
28
29	/// Generate a new V4 UUID
30	pub fn new_v4() -> Self {
31		Self(uuid::Uuid::new_v4())
32	}
33
34	/// Generate a new V7 UUID
35	pub fn new_v7() -> Self {
36		Self(uuid::Uuid::now_v7())
37	}
38
39	/// Generate a new V7 UUID
40	pub fn new_v7_from_datetime(timestamp: Datetime) -> Self {
41		let ts = uuid::Timestamp::from_unix(
42			uuid::NoContext,
43			timestamp.0.timestamp() as u64,
44			timestamp.0.timestamp_subsec_nanos(),
45		);
46		Self(uuid::Uuid::new_v7(ts))
47	}
48
49	/// Generate a new nil UUID
50	pub const fn nil() -> Self {
51		Self(uuid::Uuid::nil())
52	}
53
54	/// Generate a new max UUID
55	pub const fn max() -> Self {
56		Self(uuid::Uuid::max())
57	}
58
59	/// Generate a new UUID from a slice
60	pub fn from_slice(slice: &[u8]) -> Result<Self, uuid::Error> {
61		Ok(Self(uuid::Uuid::from_slice(slice)?))
62	}
63}
64
65impl From<uuid::Uuid> for Uuid {
66	fn from(v: uuid::Uuid) -> Self {
67		Uuid(v)
68	}
69}
70
71impl From<Uuid> for uuid::Uuid {
72	fn from(s: Uuid) -> Self {
73		s.0
74	}
75}
76
77impl From<surrealdb_types::Uuid> for Uuid {
78	fn from(v: surrealdb_types::Uuid) -> Self {
79		Uuid(v.into_inner())
80	}
81}
82
83impl From<Uuid> for surrealdb_types::Uuid {
84	fn from(x: Uuid) -> Self {
85		surrealdb_types::Uuid::from(x.0)
86	}
87}
88
89impl FromStr for Uuid {
90	type Err = uuid::Error;
91	fn from_str(s: &str) -> Result<Self, Self::Err> {
92		uuid::Uuid::try_parse(s).map(Uuid)
93	}
94}
95
96impl Deref for Uuid {
97	type Target = uuid::Uuid;
98	fn deref(&self) -> &Self::Target {
99		&self.0
100	}
101}
102
103impl Display for Uuid {
104	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
105		self.0.fmt(f)
106	}
107}
108
109impl ToSql for Uuid {
110	fn fmt_sql(&self, f: &mut String, sql_fmt: SqlFormat) {
111		write_sql!(f, sql_fmt, "u{}", QuoteStr(&self.0.to_string()))
112	}
113}
114
115#[cfg(test)]
116mod tests {
117	use super::*;
118
119	#[test]
120	fn test_uuid_to_sql_with_prefix() {
121		let uuid_str = "8424486b-85b3-4448-ac8d-5d51083391c7";
122		let uuid = Uuid::from_str(uuid_str).unwrap();
123
124		let mut output = String::new();
125		uuid.fmt_sql(&mut output, SqlFormat::SingleLine);
126
127		assert_eq!(output, format!("u'{}'", uuid_str));
128	}
129}