1use crate::{epoch::Seconds, hexbytes::Bytes};
2use rand::RngCore;
3use serde::{de, ser, Serializer};
4use std::fmt;
5#[derive(Debug, PartialEq, Clone)]
12pub enum TraceId {
13 #[doc(hidden)]
14 New(u64, [u8; 12]),
15 #[doc(hidden)]
16 Rendered(String),
17}
18
19impl TraceId {
20 pub fn new() -> Self {
22 let mut buf = [0; 12];
23 rand::thread_rng().fill_bytes(&mut buf);
24 TraceId::New(Seconds::now().trunc(), buf)
25 }
26}
27
28impl Default for TraceId {
29 fn default() -> Self {
30 TraceId::new()
31 }
32}
33
34impl fmt::Display for TraceId {
35 fn fmt(
36 &self,
37 f: &mut fmt::Formatter<'_>,
38 ) -> fmt::Result {
39 match self {
40 TraceId::New(seconds, bytes) => write!(f, "1-{:08x}-{:x}", seconds, Bytes(bytes)),
41 TraceId::Rendered(value) => write!(f, "{}", value),
42 }
43 }
44}
45
46struct TraceIdVisitor;
47
48impl<'de> de::Visitor<'de> for TraceIdVisitor {
49 type Value = TraceId;
50
51 fn expecting(
52 &self,
53 formatter: &mut fmt::Formatter,
54 ) -> fmt::Result {
55 formatter.write_str("a string value")
56 }
57 fn visit_str<E>(
58 self,
59 value: &str,
60 ) -> Result<TraceId, E>
61 where
62 E: de::Error,
63 {
64 Ok(TraceId::Rendered(value.into()))
65 }
66}
67
68impl ser::Serialize for TraceId {
69 fn serialize<S>(
70 &self,
71 serializer: S,
72 ) -> Result<S::Ok, S::Error>
73 where
74 S: Serializer,
75 {
76 serializer.serialize_str(&format!("{}", self))
77 }
78}
79
80impl<'de> de::Deserialize<'de> for TraceId {
81 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
82 where
83 D: de::Deserializer<'de>,
84 {
85 deserializer.deserialize_str(TraceIdVisitor)
86 }
87}