surrealpatch/lib/src/sql/uuid.rs
2022-06-28 11:54:04 +01:00

121 lines
2.6 KiB
Rust

use crate::sql::common::is_hex;
use crate::sql::error::IResult;
use crate::sql::serde::is_internal_serialization;
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;
use serde::{Deserialize, Serialize};
use std::fmt;
use std::ops::Deref;
use std::str;
const SINGLE: char = '\'';
const DOUBLE: char = '"';
#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd, Deserialize)]
pub struct Uuid(pub uuid::Uuid);
impl From<&str> for Uuid {
fn from(s: &str) -> Self {
match uuid::Uuid::try_parse(s) {
Ok(v) => Uuid(v),
_ => Uuid::default(),
}
}
}
impl From<String> for Uuid {
fn from(s: String) -> Self {
match uuid::Uuid::try_parse(&s) {
Ok(v) => Uuid(v),
_ => Uuid::default(),
}
}
}
impl Deref for Uuid {
type Target = uuid::Uuid;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Uuid {
pub fn new() -> Self {
Uuid(uuid::Uuid::new_v4())
}
pub fn to_raw(&self) -> String {
self.0.to_string()
}
}
impl fmt::Display for Uuid {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "\"{}\"", self.0)
}
}
impl Serialize for Uuid {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
if is_internal_serialization() {
serializer.serialize_newtype_struct("Uuid", &self.0)
} else {
serializer.serialize_some(&self.0)
}
}
}
pub fn uuid(i: &str) -> IResult<&str, Uuid> {
alt((
delimited(char(DOUBLE), uuid_raw, char(DOUBLE)),
delimited(char(SINGLE), uuid_raw, char(SINGLE)),
))(i)
}
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('-'),
alt((char('1'), char('2'), char('3'), char('4'))),
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)?;
Ok((i, Uuid::from(v)))
}
#[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;
assert_eq!("\"e72bee20-f49b-11ec-b939-0242ac120002\"", format!("{}", out));
assert_eq!(out, Uuid::from("e72bee20-f49b-11ec-b939-0242ac120002"));
}
#[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;
assert_eq!("\"b19bc00b-aa98-486c-ae37-c8e1c54295b1\"", format!("{}", out));
assert_eq!(out, Uuid::from("b19bc00b-aa98-486c-ae37-c8e1c54295b1"));
}
}