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(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36 match self {
37 TraceId::New(seconds, bytes) => write!(f, "1-{:08x}-{:x}", seconds, Bytes(bytes)),
38 TraceId::Rendered(value) => write!(f, "{}", value),
39 }
40 }
41}
42
43struct TraceIdVisitor;
44
45impl<'de> de::Visitor<'de> for TraceIdVisitor {
46 type Value = TraceId;
47
48 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
49 formatter.write_str("a string value")
50 }
51 fn visit_str<E>(self, value: &str) -> Result<TraceId, E>
52 where
53 E: de::Error,
54 {
55 Ok(TraceId::Rendered(value.into()))
56 }
57}
58
59impl ser::Serialize for TraceId {
60 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
61 where
62 S: Serializer,
63 {
64 serializer.serialize_str(&format!("{}", self))
65 }
66}
67
68impl<'de> de::Deserialize<'de> for TraceId {
69 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
70 where
71 D: de::Deserializer<'de>,
72 {
73 deserializer.deserialize_str(TraceIdVisitor)
74 }
75}