use crate::blueprint::Blueprint;
use crate::blueprint::constructor::{Constructor, RegisteredConstructor};
use crate::f;
use crate::http::HeaderValue;
use std::fmt::Formatter;
use std::hash::{Hash, Hasher};
use type_safe_id::{StaticType, TypeSafeId};
use uuid::Uuid;
#[derive(Debug, Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
pub struct ServerRequestId(TypeSafeId<SriTag>);
impl Hash for ServerRequestId {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.uuid().hash(state)
}
}
#[derive(Default, Debug, Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
struct SriTag;
impl StaticType for SriTag {
const TYPE: &'static str = "sri";
}
impl ServerRequestId {
pub fn generate() -> Self {
Self(TypeSafeId::from_uuid(Uuid::now_v7()))
}
pub fn inner(&self) -> Uuid {
self.0.uuid()
}
pub fn header_value(&self) -> HeaderValue {
self.0.to_string().try_into().unwrap()
}
}
impl From<Uuid> for ServerRequestId {
fn from(value: Uuid) -> Self {
Self(TypeSafeId::from_uuid(value))
}
}
impl std::fmt::Display for ServerRequestId {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", &self.0)
}
}
impl ServerRequestId {
pub fn register(bp: &mut Blueprint) -> RegisteredConstructor {
Self::default_constructor().register(bp)
}
pub fn default_constructor() -> Constructor {
Constructor::request_scoped(f!(super::ServerRequestId::generate))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn server_request_id() {
let request_id = ServerRequestId::generate();
let header_value = request_id.header_value();
let header_value = header_value.to_str().unwrap();
assert!(header_value.starts_with("sri_"));
assert_eq!(header_value.len(), 3 + 1 + 26)
}
}