1use std::fmt;
2use std::hash::Hash;
3use std::num::ParseIntError;
4use std::ops::{BitAnd, BitOr, Not};
5
6#[derive(Clone, Debug, Default, PartialEq, Eq, Copy, Hash)]
16pub struct TraceFlags(u8);
17
18impl TraceFlags {
19 pub const NOT_SAMPLED: TraceFlags = TraceFlags(0x00);
26
27 pub const SAMPLED: TraceFlags = TraceFlags(0x01);
34
35 pub const fn new(flags: u8) -> Self {
37 TraceFlags(flags)
38 }
39
40 pub fn is_sampled(&self) -> bool {
42 (*self & TraceFlags::SAMPLED) == TraceFlags::SAMPLED
43 }
44
45 pub fn with_sampled(&self, sampled: bool) -> Self {
47 if sampled {
48 *self | TraceFlags::SAMPLED
49 } else {
50 *self & !TraceFlags::SAMPLED
51 }
52 }
53
54 pub fn to_u8(self) -> u8 {
56 self.0
57 }
58}
59
60impl BitAnd for TraceFlags {
61 type Output = Self;
62
63 fn bitand(self, rhs: Self) -> Self::Output {
64 Self(self.0 & rhs.0)
65 }
66}
67
68impl BitOr for TraceFlags {
69 type Output = Self;
70
71 fn bitor(self, rhs: Self) -> Self::Output {
72 Self(self.0 | rhs.0)
73 }
74}
75
76impl Not for TraceFlags {
77 type Output = Self;
78
79 fn not(self) -> Self::Output {
80 Self(!self.0)
81 }
82}
83
84impl fmt::LowerHex for TraceFlags {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 fmt::LowerHex::fmt(&self.0, f)
87 }
88}
89
90#[derive(Clone, PartialEq, Eq, Copy, Hash)]
94pub struct TraceId(u128);
95
96impl TraceId {
97 pub const INVALID: TraceId = TraceId(0);
99
100 pub const fn from_bytes(bytes: [u8; 16]) -> Self {
102 TraceId(u128::from_be_bytes(bytes))
103 }
104
105 pub const fn to_bytes(self) -> [u8; 16] {
107 self.0.to_be_bytes()
108 }
109
110 pub fn from_hex(hex: &str) -> Result<Self, ParseIntError> {
123 u128::from_str_radix(hex, 16).map(TraceId)
124 }
125}
126
127impl From<u128> for TraceId {
128 fn from(value: u128) -> Self {
129 TraceId(value)
130 }
131}
132
133impl fmt::Debug for TraceId {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 f.write_fmt(format_args!("{:032x}", self.0))
136 }
137}
138
139impl fmt::Display for TraceId {
140 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141 f.write_fmt(format_args!("{:032x}", self.0))
142 }
143}
144
145impl fmt::LowerHex for TraceId {
146 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147 fmt::LowerHex::fmt(&self.0, f)
148 }
149}
150
151#[derive(Clone, PartialEq, Eq, Copy, Hash)]
155pub struct SpanId(u64);
156
157impl SpanId {
158 pub const INVALID: SpanId = SpanId(0);
160
161 pub const fn from_bytes(bytes: [u8; 8]) -> Self {
163 SpanId(u64::from_be_bytes(bytes))
164 }
165
166 pub const fn to_bytes(self) -> [u8; 8] {
168 self.0.to_be_bytes()
169 }
170
171 pub fn from_hex(hex: &str) -> Result<Self, ParseIntError> {
184 u64::from_str_radix(hex, 16).map(SpanId)
185 }
186}
187
188impl From<u64> for SpanId {
189 fn from(value: u64) -> Self {
190 SpanId(value)
191 }
192}
193
194impl fmt::Debug for SpanId {
195 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
196 f.write_fmt(format_args!("{:016x}", self.0))
197 }
198}
199
200impl fmt::Display for SpanId {
201 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
202 f.write_fmt(format_args!("{:016x}", self.0))
203 }
204}
205
206impl fmt::LowerHex for SpanId {
207 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
208 fmt::LowerHex::fmt(&self.0, f)
209 }
210}
211
212#[cfg(test)]
213mod tests {
214 use super::*;
215
216 #[rustfmt::skip]
217 fn trace_id_test_data() -> Vec<(TraceId, &'static str, [u8; 16])> {
218 vec![
219 (TraceId(0), "00000000000000000000000000000000", [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
220 (TraceId(42), "0000000000000000000000000000002a", [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42]),
221 (TraceId(126642714606581564793456114182061442190), "5f467fe7bf42676c05e20ba4a90e448e", [95, 70, 127, 231, 191, 66, 103, 108, 5, 226, 11, 164, 169, 14, 68, 142])
222 ]
223 }
224
225 #[rustfmt::skip]
226 fn span_id_test_data() -> Vec<(SpanId, &'static str, [u8; 8])> {
227 vec![
228 (SpanId(0), "0000000000000000", [0, 0, 0, 0, 0, 0, 0, 0]),
229 (SpanId(42), "000000000000002a", [0, 0, 0, 0, 0, 0, 0, 42]),
230 (SpanId(5508496025762705295), "4c721bf33e3caf8f", [76, 114, 27, 243, 62, 60, 175, 143])
231 ]
232 }
233
234 #[test]
235 fn test_trace_id() {
236 for test_case in trace_id_test_data() {
237 assert_eq!(format!("{}", test_case.0), test_case.1);
238 assert_eq!(format!("{:032x}", test_case.0), test_case.1);
239 assert_eq!(test_case.0.to_bytes(), test_case.2);
240
241 assert_eq!(test_case.0, TraceId::from_hex(test_case.1).unwrap());
242 assert_eq!(test_case.0, TraceId::from_bytes(test_case.2));
243 }
244 }
245
246 #[test]
247 fn test_span_id() {
248 for test_case in span_id_test_data() {
249 assert_eq!(format!("{}", test_case.0), test_case.1);
250 assert_eq!(format!("{:016x}", test_case.0), test_case.1);
251 assert_eq!(test_case.0.to_bytes(), test_case.2);
252
253 assert_eq!(test_case.0, SpanId::from_hex(test_case.1).unwrap());
254 assert_eq!(test_case.0, SpanId::from_bytes(test_case.2));
255 }
256 }
257}