use std::fmt;
use std::str::FromStr;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, schemars::JsonSchema)]
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
pub struct RequestId(String);
impl RequestId {
#[must_use]
pub fn now_v7() -> Self {
Self(uuid::Uuid::now_v7().to_string())
}
pub fn parse(value: &str) -> Result<Self, RequestIdError> {
if is_uuid7(value) {
return Ok(Self(value.to_string()));
}
Err(RequestIdError::Invalid)
}
#[must_use]
pub fn as_str(&self) -> &str {
&self.0
}
}
fn is_uuid7(value: &str) -> bool {
uuid::Uuid::parse_str(value).is_ok_and(|uuid| uuid.get_version_num() == 7)
}
impl fmt::Display for RequestId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.0)
}
}
impl FromStr for RequestId {
type Err = RequestIdError;
fn from_str(value: &str) -> Result<Self, Self::Err> {
Self::parse(value)
}
}
#[derive(Debug, thiserror::Error)]
pub enum RequestIdError {
#[error("invalid request id")]
Invalid,
}