1//! `MakeVisitor` wrappers for working with `fmt::Display` fields.
2use super::{MakeVisitor, VisitFmt, VisitOutput};
3use tracing_core::field::{Field, Visit};
4
5use core::fmt;
6
7/// A visitor wrapper that ensures any strings named "message" are formatted
8/// using `fmt::Display`
9#[derive(Debug, Clone)]
10pub struct Messages<V>(V);
11
12// TODO(eliza): When `error` as a primitive type is stable, add a
13// `DisplayErrors` wrapper...
14
15// === impl Messages ===
16//
17impl<V> Messages<V> {
18 /// Returns a new [`MakeVisitor`] implementation that will wrap `inner` so
19 /// that any strings named `message` are formatted using `fmt::Display`.
20 ///
21 /// [`MakeVisitor`]: super::MakeVisitor
22 pub fn new(inner: V) -> Self {
23 Messages(inner)
24 }
25}
26
27impl<T, V> MakeVisitor<T> for Messages<V>
28where
29 V: MakeVisitor<T>,
30{
31 type Visitor = Messages<V::Visitor>;
32
33 #[inline]
34 fn make_visitor(&self, target: T) -> Self::Visitor {
35 Messages(self.0.make_visitor(target))
36 }
37}
38
39impl<V> Visit for Messages<V>
40where
41 V: Visit,
42{
43 #[inline]
44 fn record_f64(&mut self, field: &Field, value: f64) {
45 self.0.record_f64(field, value)
46 }
47
48 #[inline]
49 fn record_i64(&mut self, field: &Field, value: i64) {
50 self.0.record_i64(field, value)
51 }
52
53 #[inline]
54 fn record_u64(&mut self, field: &Field, value: u64) {
55 self.0.record_u64(field, value)
56 }
57
58 #[inline]
59 fn record_bool(&mut self, field: &Field, value: bool) {
60 self.0.record_bool(field, value)
61 }
62
63 /// Visit a string value.
64 fn record_str(&mut self, field: &Field, value: &str) {
65 if field.name() == "message" {
66 self.0.record_debug(field, &format_args!("{}", value))
67 } else {
68 self.0.record_str(field, value)
69 }
70 }
71
72 // TODO(eliza): add RecordError when stable
73 // fn record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static)) {
74 // self.record_debug(field, &format_args!("{}", value))
75 // }
76
77 #[inline]
78 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
79 self.0.record_debug(field, value)
80 }
81}
82
83impl<V, O> VisitOutput<O> for Messages<V>
84where
85 V: VisitOutput<O>,
86{
87 #[inline]
88 fn finish(self) -> O {
89 self.0.finish()
90 }
91}
92
93feature! {
94 #![feature = "std"]
95 use super::VisitWrite;
96 use std::io;
97
98 impl<V> VisitWrite for Messages<V>
99 where
100 V: VisitWrite,
101 {
102 #[inline]
103 fn writer(&mut self) -> &mut dyn io::Write {
104 self.0.writer()
105 }
106 }
107}
108
109impl<V> VisitFmt for Messages<V>
110where
111 V: VisitFmt,
112{
113 #[inline]
114 fn writer(&mut self) -> &mut dyn fmt::Write {
115 self.0.writer()
116 }
117}
118