use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
#[serde(try_from = "String", into = "String")]
pub struct ID(uuid::Uuid);
impl ID {
pub fn new() -> Self {
Self(uuid::Uuid::new_v4())
}
}
impl Default for ID {
fn default() -> Self {
Self::new()
}
}
impl TryFrom<String> for ID {
type Error = uuid::Error;
fn try_from(value: String) -> Result<Self, Self::Error> {
value.parse()
}
}
impl core::str::FromStr for ID {
type Err = uuid::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(ID(uuid::Uuid::parse_str(s)?))
}
}
impl core::fmt::Display for ID {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<ID> for String {
fn from(value: ID) -> Self {
value.to_string()
}
}
impl core::ops::Deref for ID {
type Target = uuid::Uuid;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[cfg(test)]
mod tests {
use super::*;
use core::ops::Deref;
#[test]
fn test_id_creation() {
let id = ID::new();
let id_str: String = id.into();
let parsed = ID::try_from(id_str.clone()).unwrap();
assert_eq!(id, parsed);
assert_eq!(id.to_string(), id_str);
}
#[test]
fn test_new_id() {
let id = ID::new();
assert!(uuid::Uuid::parse_str(&id.to_string()).is_ok());
}
#[test]
fn test_id_conversion() {
let id = ID::new();
let id_string = String::from(id);
let converted_id = ID::try_from(id_string.clone()).unwrap();
assert_eq!(id, converted_id);
assert_eq!(id.to_string(), id_string);
}
#[test]
fn test_invalid_id() {
let result = ID::try_from("not-a-uuid".to_string());
assert!(result.is_err());
}
#[test]
fn test_id_deref() {
let id = ID::new();
let uuid: &uuid::Uuid = id.deref();
assert_eq!(uuid.to_string(), id.to_string());
}
#[test]
fn test_id_display() {
let id = ID::new();
let uuid_string = id.0.to_string();
assert_eq!(id.to_string(), uuid_string);
}
}