tracing_tunnel/
values.rs

1//! `TracedValues` and closely related types.
2
3use serde::{
4    de::{MapAccess, Visitor},
5    ser::SerializeMap,
6    Deserialize, Deserializer, Serialize, Serializer,
7};
8use tracing_core::{
9    field::{Field, ValueSet, Visit},
10    span::Record,
11    Event,
12};
13
14use core::{fmt, mem, ops, slice};
15
16use crate::{
17    alloc::{vec, String, Vec},
18    TracedValue,
19};
20
21/// Collection of named [`TracedValue`]s.
22///
23/// Functionally this collection is similar to a `HashMap<S, TracedValue>`,
24/// with the key difference being that the order of [iteration](Self::iter()) is the insertion order.
25/// If a value is updated, including via [`Extend`] etc., it preserves its old placement.
26#[derive(Clone)]
27pub struct TracedValues<S> {
28    // Using `Vec` for entries is inefficient for random access, but seems acceptable given that
29    // valid value sets have no more than 32 values. We need this (vs using `linked_hash_map`)
30    // for no-std compatibility.
31    inner: Vec<(S, TracedValue)>,
32}
33
34impl<S> Default for TracedValues<S> {
35    fn default() -> Self {
36        Self { inner: Vec::new() }
37    }
38}
39
40impl<S: AsRef<str>> fmt::Debug for TracedValues<S> {
41    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
42        let mut map = formatter.debug_map();
43        for (name, value) in &self.inner {
44            map.entry(&name.as_ref(), value);
45        }
46        map.finish()
47    }
48}
49
50impl<S: From<&'static str> + AsRef<str>> TracedValues<S> {
51    /// Creates traced values from the specified value set.
52    pub fn from_values(values: &ValueSet<'_>) -> Self {
53        let mut visitor = TracedValueVisitor {
54            values: Self::default(),
55        };
56        values.record(&mut visitor);
57        visitor.values
58    }
59
60    /// Creates traced values from the specified record.
61    pub fn from_record(values: &Record<'_>) -> Self {
62        let mut visitor = TracedValueVisitor {
63            values: Self::default(),
64        };
65        values.record(&mut visitor);
66        visitor.values
67    }
68
69    /// Creates traced values from the values in the specified event.
70    pub fn from_event(event: &Event<'_>) -> Self {
71        let mut visitor = TracedValueVisitor {
72            values: Self::default(),
73        };
74        event.record(&mut visitor);
75        visitor.values
76    }
77}
78
79impl<S: AsRef<str>> TracedValues<S> {
80    /// Creates new empty values.
81    pub fn new() -> Self {
82        Self::default()
83    }
84
85    /// Returns the number of stored values.
86    pub fn len(&self) -> usize {
87        self.inner.len()
88    }
89
90    /// Checks whether this collection of values is empty.
91    pub fn is_empty(&self) -> bool {
92        self.inner.is_empty()
93    }
94
95    /// Returns the value with the specified name, or `None` if it not set.
96    pub fn get(&self, name: &str) -> Option<&TracedValue> {
97        self.inner.iter().find_map(|(existing_name, value)| {
98            if existing_name.as_ref() == name {
99                Some(value)
100            } else {
101                None
102            }
103        })
104    }
105
106    /// Iterates over the contained name-value pairs.
107    pub fn iter(&self) -> TracedValuesIter<'_, S> {
108        TracedValuesIter {
109            inner: self.inner.iter(),
110        }
111    }
112
113    /// Inserts a value with the specified name. If a value with the same name was present
114    /// previously, it is overwritten. Returns the previous value with the specified name,
115    /// if any.
116    pub fn insert(&mut self, name: S, value: TracedValue) -> Option<TracedValue> {
117        let position = self
118            .inner
119            .iter()
120            .position(|(existing_name, _)| existing_name.as_ref() == name.as_ref());
121        if let Some(position) = position {
122            let place = &mut self.inner[position].1;
123            Some(mem::replace(place, value))
124        } else {
125            self.inner.push((name, value));
126            None
127        }
128    }
129}
130
131impl<S: AsRef<str>> ops::Index<&str> for TracedValues<S> {
132    type Output = TracedValue;
133
134    fn index(&self, index: &str) -> &Self::Output {
135        self.get(index)
136            .unwrap_or_else(|| panic!("value `{index}` is not defined"))
137    }
138}
139
140impl<S: AsRef<str>> FromIterator<(S, TracedValue)> for TracedValues<S> {
141    fn from_iter<I: IntoIterator<Item = (S, TracedValue)>>(iter: I) -> Self {
142        let iter = iter.into_iter();
143        let mut this = Self::new();
144        this.extend(iter);
145        this
146    }
147}
148
149impl<S: AsRef<str>> Extend<(S, TracedValue)> for TracedValues<S> {
150    fn extend<I: IntoIterator<Item = (S, TracedValue)>>(&mut self, iter: I) {
151        let iter = iter.into_iter();
152        self.inner.reserve(iter.size_hint().0);
153        for (name, value) in iter {
154            self.insert(name, value);
155        }
156    }
157}
158
159impl<S> IntoIterator for TracedValues<S> {
160    type Item = (S, TracedValue);
161    type IntoIter = vec::IntoIter<(S, TracedValue)>;
162
163    fn into_iter(self) -> Self::IntoIter {
164        self.inner.into_iter()
165    }
166}
167
168/// Iterator over name-value references returned from [`TracedValues::iter()`].
169#[derive(Debug)]
170pub struct TracedValuesIter<'a, S> {
171    inner: slice::Iter<'a, (S, TracedValue)>,
172}
173
174impl<'a, S: AsRef<str>> Iterator for TracedValuesIter<'a, S> {
175    type Item = (&'a str, &'a TracedValue);
176
177    fn next(&mut self) -> Option<Self::Item> {
178        self.inner
179            .next()
180            .map(|(name, value)| (name.as_ref(), value))
181    }
182
183    fn size_hint(&self) -> (usize, Option<usize>) {
184        self.inner.size_hint()
185    }
186}
187
188impl<'a, S: AsRef<str>> DoubleEndedIterator for TracedValuesIter<'a, S> {
189    fn next_back(&mut self) -> Option<Self::Item> {
190        self.inner
191            .next_back()
192            .map(|(name, value)| (name.as_ref(), value))
193    }
194}
195
196impl<'a, S: AsRef<str>> ExactSizeIterator for TracedValuesIter<'a, S> {
197    fn len(&self) -> usize {
198        self.inner.len()
199    }
200}
201
202impl<'a, S: AsRef<str>> IntoIterator for &'a TracedValues<S> {
203    type Item = (&'a str, &'a TracedValue);
204    type IntoIter = TracedValuesIter<'a, S>;
205
206    fn into_iter(self) -> Self::IntoIter {
207        self.iter()
208    }
209}
210
211impl<S: AsRef<str>> Serialize for TracedValues<S> {
212    fn serialize<Ser: Serializer>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error> {
213        let mut map = serializer.serialize_map(Some(self.len()))?;
214        for (name, value) in self {
215            map.serialize_entry(name, value)?;
216        }
217        map.end()
218    }
219}
220
221impl<'de> Deserialize<'de> for TracedValues<String> {
222    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
223    where
224        D: Deserializer<'de>,
225    {
226        struct MapVisitor;
227
228        impl<'v> Visitor<'v> for MapVisitor {
229            type Value = TracedValues<String>;
230
231            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
232                formatter.write_str("map of name-value entries")
233            }
234
235            fn visit_map<A: MapAccess<'v>>(self, mut map: A) -> Result<Self::Value, A::Error> {
236                let mut values = TracedValues {
237                    inner: Vec::with_capacity(map.size_hint().unwrap_or(0)),
238                };
239                while let Some((name, value)) = map.next_entry()? {
240                    values.insert(name, value);
241                }
242                Ok(values)
243            }
244        }
245
246        deserializer.deserialize_map(MapVisitor)
247    }
248}
249
250struct TracedValueVisitor<S> {
251    values: TracedValues<S>,
252}
253
254impl<S: AsRef<str>> fmt::Debug for TracedValueVisitor<S> {
255    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
256        formatter
257            .debug_struct("ValueVisitor")
258            .field("values", &self.values)
259            .finish()
260    }
261}
262
263impl<S: From<&'static str> + AsRef<str>> Visit for TracedValueVisitor<S> {
264    fn record_f64(&mut self, field: &Field, value: f64) {
265        self.values.insert(field.name().into(), value.into());
266    }
267
268    fn record_i64(&mut self, field: &Field, value: i64) {
269        self.values.insert(field.name().into(), value.into());
270    }
271
272    fn record_u64(&mut self, field: &Field, value: u64) {
273        self.values.insert(field.name().into(), value.into());
274    }
275
276    fn record_i128(&mut self, field: &Field, value: i128) {
277        self.values.insert(field.name().into(), value.into());
278    }
279
280    fn record_u128(&mut self, field: &Field, value: u128) {
281        self.values.insert(field.name().into(), value.into());
282    }
283
284    fn record_bool(&mut self, field: &Field, value: bool) {
285        self.values.insert(field.name().into(), value.into());
286    }
287
288    fn record_str(&mut self, field: &Field, value: &str) {
289        self.values.insert(field.name().into(), value.into());
290    }
291
292    #[cfg(feature = "std")]
293    fn record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static)) {
294        self.values
295            .insert(field.name().into(), TracedValue::error(value));
296    }
297
298    fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
299        self.values
300            .insert(field.name().into(), TracedValue::debug(value));
301    }
302}