1use data_encoding::{DecodeError, HEXLOWER_PERMISSIVE};
17use std::error::Error;
18use std::fmt;
19use std::str::FromStr;
20
21#[derive(Copy, Clone, Debug, PartialEq, Eq)]
22enum Inner {
23 Short([u8; 8]),
24 Long([u8; 16]),
25}
26
27#[derive(Copy, Clone, Debug, PartialEq, Eq)]
32pub struct TraceId(Inner);
33
34impl fmt::Display for TraceId {
35 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
36 for b in self.bytes() {
37 write!(fmt, "{:02x}", b)?;
38 }
39 Ok(())
40 }
41}
42
43impl FromStr for TraceId {
44 type Err = TraceIdParseError;
45
46 fn from_str(s: &str) -> Result<TraceId, TraceIdParseError> {
47 let inner = match HEXLOWER_PERMISSIVE.decode_len(s.len()) {
48 Ok(8) => {
49 let mut buf = [0; 8];
50 HEXLOWER_PERMISSIVE
51 .decode_mut(s.as_bytes(), &mut buf)
52 .map_err(|e| TraceIdParseError(Some(e.error)))?;
53 Inner::Short(buf)
54 }
55 Ok(16) => {
56 let mut buf = [0; 16];
57 HEXLOWER_PERMISSIVE
58 .decode_mut(s.as_bytes(), &mut buf)
59 .map_err(|e| TraceIdParseError(Some(e.error)))?;
60 Inner::Long(buf)
61 }
62 _ => return Err(TraceIdParseError(None)),
63 };
64
65 Ok(TraceId(inner))
66 }
67}
68
69#[cfg(feature = "serde")]
70mod serde {
71 use crate::trace_id::TraceId;
72 use serde::de::{Error, Unexpected, Visitor};
73 use serde::{Deserialize, Deserializer, Serialize, Serializer};
74 use std::fmt;
75
76 impl Serialize for TraceId {
77 fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
78 where
79 S: Serializer,
80 {
81 s.collect_str(self)
82 }
83 }
84
85 impl<'de> Deserialize<'de> for TraceId {
86 fn deserialize<D>(d: D) -> Result<TraceId, D::Error>
87 where
88 D: Deserializer<'de>,
89 {
90 d.deserialize_str(V)
91 }
92 }
93
94 struct V;
95
96 impl<'de> Visitor<'de> for V {
97 type Value = TraceId;
98
99 fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
100 fmt.write_str("a hex-encoded trace ID")
101 }
102
103 fn visit_str<E>(self, v: &str) -> Result<TraceId, E>
104 where
105 E: Error,
106 {
107 v.parse()
108 .map_err(|_| Error::invalid_value(Unexpected::Str(v), &self))
109 }
110 }
111}
112
113impl TraceId {
114 #[inline]
116 pub fn bytes(&self) -> &[u8] {
117 match self.0 {
118 Inner::Short(ref buf) => buf,
119 Inner::Long(ref buf) => buf,
120 }
121 }
122}
123
124impl From<[u8; 8]> for TraceId {
125 #[inline]
126 fn from(bytes: [u8; 8]) -> TraceId {
127 TraceId(Inner::Short(bytes))
128 }
129}
130
131impl From<[u8; 16]> for TraceId {
132 #[inline]
133 fn from(bytes: [u8; 16]) -> TraceId {
134 TraceId(Inner::Long(bytes))
135 }
136}
137
138#[derive(Debug)]
140pub struct TraceIdParseError(Option<DecodeError>);
141
142impl fmt::Display for TraceIdParseError {
143 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
144 fmt.write_str("error parsing trace ID: ")?;
145 match self.0 {
146 Some(ref err) => write!(fmt, "{}", err),
147 None => fmt.write_str("invalid length"),
148 }
149 }
150}
151
152impl Error for TraceIdParseError {
153 fn source(&self) -> Option<&(dyn Error + 'static)> {
154 self.0.as_ref().map(|e| e as _)
155 }
156}