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