2022-06-25 22:37:45 +00:00
|
|
|
use crate::sql::common::is_hex;
|
|
|
|
use crate::sql::error::IResult;
|
2023-05-31 07:36:29 +00:00
|
|
|
use crate::sql::escape::quote_str;
|
2023-04-25 10:13:04 +00:00
|
|
|
use crate::sql::strand::Strand;
|
2022-06-25 22:37:45 +00:00
|
|
|
use nom::branch::alt;
|
|
|
|
use nom::bytes::complete::take_while_m_n;
|
|
|
|
use nom::character::complete::char;
|
|
|
|
use nom::combinator::recognize;
|
|
|
|
use nom::sequence::delimited;
|
|
|
|
use nom::sequence::tuple;
|
2023-08-17 18:03:46 +00:00
|
|
|
use revision::revisioned;
|
2022-06-25 22:37:45 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
2022-10-16 21:25:19 +00:00
|
|
|
use std::fmt::{self, Display, Formatter};
|
2022-06-25 22:37:45 +00:00
|
|
|
use std::ops::Deref;
|
|
|
|
use std::str;
|
2023-04-25 10:13:04 +00:00
|
|
|
use std::str::FromStr;
|
2022-06-25 22:37:45 +00:00
|
|
|
|
2023-03-30 10:41:44 +00:00
|
|
|
pub(crate) const TOKEN: &str = "$surrealdb::private::sql::Uuid";
|
|
|
|
|
2023-04-29 15:58:22 +00:00
|
|
|
#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
|
|
|
|
#[serde(rename = "$surrealdb::private::sql::Uuid")]
|
2023-08-17 18:03:46 +00:00
|
|
|
#[revisioned(revision = 1)]
|
2023-09-03 08:35:16 +00:00
|
|
|
pub struct Uuid(pub uuid::Uuid);
|
2022-06-25 22:37:45 +00:00
|
|
|
|
2022-10-25 09:41:16 +00:00
|
|
|
impl From<uuid::Uuid> for Uuid {
|
|
|
|
fn from(v: uuid::Uuid) -> Self {
|
|
|
|
Uuid(v)
|
|
|
|
}
|
2022-10-24 08:43:50 +00:00
|
|
|
}
|
|
|
|
|
2022-10-28 11:35:01 +00:00
|
|
|
impl From<Uuid> for uuid::Uuid {
|
|
|
|
fn from(s: Uuid) -> Self {
|
|
|
|
s.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-25 10:13:04 +00:00
|
|
|
impl FromStr for Uuid {
|
|
|
|
type Err = ();
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
|
Self::try_from(s)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TryFrom<String> for Uuid {
|
|
|
|
type Error = ();
|
|
|
|
fn try_from(v: String) -> Result<Self, Self::Error> {
|
|
|
|
Self::try_from(v.as_str())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TryFrom<Strand> for Uuid {
|
|
|
|
type Error = ();
|
|
|
|
fn try_from(v: Strand) -> Result<Self, Self::Error> {
|
|
|
|
Self::try_from(v.as_str())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TryFrom<&str> for Uuid {
|
|
|
|
type Error = ();
|
|
|
|
fn try_from(v: &str) -> Result<Self, Self::Error> {
|
|
|
|
match uuid::Uuid::try_parse(v) {
|
|
|
|
Ok(v) => Ok(Self(v)),
|
|
|
|
Err(_) => Err(()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-25 22:37:45 +00:00
|
|
|
impl Deref for Uuid {
|
|
|
|
type Target = uuid::Uuid;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Uuid {
|
2022-10-19 09:55:19 +00:00
|
|
|
/// Generate a new V4 UUID
|
2022-06-25 22:37:45 +00:00
|
|
|
pub fn new() -> Self {
|
2023-01-17 09:51:58 +00:00
|
|
|
#[cfg(uuid_unstable)]
|
|
|
|
{
|
|
|
|
Self(uuid::Uuid::now_v7())
|
|
|
|
}
|
|
|
|
#[cfg(not(uuid_unstable))]
|
|
|
|
{
|
|
|
|
Self(uuid::Uuid::new_v4())
|
|
|
|
}
|
2022-06-25 22:37:45 +00:00
|
|
|
}
|
2022-10-19 09:55:19 +00:00
|
|
|
/// Generate a new V4 UUID
|
2022-10-16 22:22:34 +00:00
|
|
|
pub fn new_v4() -> Self {
|
|
|
|
Self(uuid::Uuid::new_v4())
|
|
|
|
}
|
2022-10-19 09:55:19 +00:00
|
|
|
/// Generate a new V7 UUID
|
2022-10-25 22:17:21 +00:00
|
|
|
#[cfg(uuid_unstable)]
|
2022-10-16 22:22:34 +00:00
|
|
|
pub fn new_v7() -> Self {
|
|
|
|
Self(uuid::Uuid::now_v7())
|
|
|
|
}
|
2022-10-19 09:55:19 +00:00
|
|
|
/// Convert the Uuid to a raw String
|
2022-06-25 22:37:45 +00:00
|
|
|
pub fn to_raw(&self) -> String {
|
|
|
|
self.0.to_string()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-16 21:25:19 +00:00
|
|
|
impl Display for Uuid {
|
|
|
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
2023-05-31 07:36:29 +00:00
|
|
|
Display::fmt("e_str(&self.0.to_string()), f)
|
2022-06-25 22:37:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn uuid(i: &str) -> IResult<&str, Uuid> {
|
2022-10-16 20:35:50 +00:00
|
|
|
alt((uuid_single, uuid_double))(i)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn uuid_single(i: &str) -> IResult<&str, Uuid> {
|
|
|
|
delimited(char('\''), uuid_raw, char('\''))(i)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn uuid_double(i: &str) -> IResult<&str, Uuid> {
|
|
|
|
delimited(char('\"'), uuid_raw, char('\"'))(i)
|
2022-06-25 22:37:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn uuid_raw(i: &str) -> IResult<&str, Uuid> {
|
|
|
|
let (i, v) = recognize(tuple((
|
|
|
|
take_while_m_n(8, 8, is_hex),
|
|
|
|
char('-'),
|
|
|
|
take_while_m_n(4, 4, is_hex),
|
|
|
|
char('-'),
|
2022-10-16 14:42:15 +00:00
|
|
|
alt((
|
|
|
|
char('1'),
|
|
|
|
char('2'),
|
|
|
|
char('3'),
|
|
|
|
char('4'),
|
|
|
|
char('5'),
|
|
|
|
char('6'),
|
|
|
|
char('7'),
|
|
|
|
char('8'),
|
|
|
|
)),
|
2022-06-25 22:37:45 +00:00
|
|
|
take_while_m_n(3, 3, is_hex),
|
|
|
|
char('-'),
|
|
|
|
take_while_m_n(4, 4, is_hex),
|
|
|
|
char('-'),
|
|
|
|
take_while_m_n(12, 12, is_hex),
|
|
|
|
)))(i)?;
|
2023-04-25 10:13:04 +00:00
|
|
|
Ok((i, Uuid::try_from(v).unwrap()))
|
2022-06-25 22:37:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn uuid_v1() {
|
|
|
|
let sql = "e72bee20-f49b-11ec-b939-0242ac120002";
|
|
|
|
let res = uuid_raw(sql);
|
|
|
|
assert!(res.is_ok());
|
|
|
|
let out = res.unwrap().1;
|
2022-10-19 14:48:50 +00:00
|
|
|
assert_eq!("'e72bee20-f49b-11ec-b939-0242ac120002'", format!("{}", out));
|
2023-04-25 10:13:04 +00:00
|
|
|
assert_eq!(out, Uuid::try_from("e72bee20-f49b-11ec-b939-0242ac120002").unwrap());
|
2022-06-25 22:37:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn uuid_v4() {
|
|
|
|
let sql = "b19bc00b-aa98-486c-ae37-c8e1c54295b1";
|
|
|
|
let res = uuid_raw(sql);
|
|
|
|
assert!(res.is_ok());
|
|
|
|
let out = res.unwrap().1;
|
2022-10-19 14:48:50 +00:00
|
|
|
assert_eq!("'b19bc00b-aa98-486c-ae37-c8e1c54295b1'", format!("{}", out));
|
2023-04-25 10:13:04 +00:00
|
|
|
assert_eq!(out, Uuid::try_from("b19bc00b-aa98-486c-ae37-c8e1c54295b1").unwrap());
|
2022-06-25 22:37:45 +00:00
|
|
|
}
|
|
|
|
}
|