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)]
25pub struct SpanId {
26 buf: [u8; 8],
27}
28
29impl FromStr for SpanId {
30 type Err = SpanIdParseError;
31
32 fn from_str(s: &str) -> Result<SpanId, SpanIdParseError> {
33 let mut buf = [0; 8];
34 match HEXLOWER_PERMISSIVE.decode_len(s.len()) {
35 Ok(8) => {
36 HEXLOWER_PERMISSIVE
37 .decode_mut(s.as_bytes(), &mut buf)
38 .map_err(|e| SpanIdParseError(Some(e.error)))?;
39 }
40 _ => return Err(SpanIdParseError(None)),
41 }
42
43 Ok(SpanId { buf })
44 }
45}
46
47impl fmt::Display for SpanId {
48 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
49 for b in self.bytes() {
50 write!(fmt, "{:02x}", b)?;
51 }
52 Ok(())
53 }
54}
55
56#[cfg(feature = "serde")]
57mod serde {
58 use crate::span_id::SpanId;
59 use serde::de::{Error, Unexpected, Visitor};
60 use serde::{Deserialize, Deserializer, Serialize, Serializer};
61 use std::fmt;
62
63 impl Serialize for SpanId {
64 fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
65 where
66 S: Serializer,
67 {
68 s.collect_str(self)
69 }
70 }
71
72 impl<'de> Deserialize<'de> for SpanId {
73 fn deserialize<D>(d: D) -> Result<SpanId, D::Error>
74 where
75 D: Deserializer<'de>,
76 {
77 d.deserialize_str(V)
78 }
79 }
80
81 struct V;
82
83 impl<'de> Visitor<'de> for V {
84 type Value = SpanId;
85
86 fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
87 fmt.write_str("a hex-encoded span ID")
88 }
89
90 fn visit_str<E>(self, v: &str) -> Result<SpanId, E>
91 where
92 E: Error,
93 {
94 v.parse()
95 .map_err(|_| Error::invalid_value(Unexpected::Str(v), &self))
96 }
97 }
98}
99
100impl SpanId {
101 #[inline]
103 pub fn bytes(&self) -> &[u8] {
104 &self.buf
105 }
106}
107
108impl From<[u8; 8]> for SpanId {
109 #[inline]
110 fn from(bytes: [u8; 8]) -> SpanId {
111 SpanId { buf: bytes }
112 }
113}
114
115#[derive(Debug)]
117pub struct SpanIdParseError(Option<DecodeError>);
118
119impl fmt::Display for SpanIdParseError {
120 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
121 fmt.write_str("error parsing span: ")?;
122 match self.0 {
123 Some(ref err) => write!(fmt, "{}", err),
124 None => fmt.write_str("invalid length"),
125 }
126 }
127}
128
129impl Error for SpanIdParseError {
130 fn source(&self) -> Option<&(dyn Error + 'static)> {
131 self.0.as_ref().map(|e| e as _)
132 }
133}