]> git.proxmox.com Git - rustc.git/blob - vendor/tracing-subscriber-0.3.3/src/field/delimited.rs
New upstream version 1.66.0+dfsg1
[rustc.git] / vendor / tracing-subscriber-0.3.3 / src / field / delimited.rs
1 //! A `MakeVisitor` wrapper that separates formatted fields with a delimiter.
2 use super::{MakeVisitor, VisitFmt, VisitOutput};
3
4 use core::fmt;
5 use tracing_core::field::{Field, Visit};
6
7 /// A `MakeVisitor` wrapper that wraps a visitor that writes formatted output so
8 /// that a delimiter is inserted between writing formatted field values.
9 #[derive(Debug, Clone)]
10 pub struct Delimited<D, V> {
11 delimiter: D,
12 inner: V,
13 }
14
15 /// A visitor wrapper that inserts a delimiter after the wrapped visitor formats
16 /// a field value.
17 #[derive(Debug)]
18 pub struct VisitDelimited<D, V> {
19 delimiter: D,
20 seen: bool,
21 inner: V,
22 err: fmt::Result,
23 }
24
25 // === impl Delimited ===
26
27 impl<D, V, T> MakeVisitor<T> for Delimited<D, V>
28 where
29 D: AsRef<str> + Clone,
30 V: MakeVisitor<T>,
31 V::Visitor: VisitFmt,
32 {
33 type Visitor = VisitDelimited<D, V::Visitor>;
34 fn make_visitor(&self, target: T) -> Self::Visitor {
35 let inner = self.inner.make_visitor(target);
36 VisitDelimited::new(self.delimiter.clone(), inner)
37 }
38 }
39
40 impl<D, V> Delimited<D, V> {
41 /// Returns a new [`MakeVisitor`] implementation that wraps `inner` so that
42 /// it will format each visited field separated by the provided `delimiter`.
43 ///
44 /// [`MakeVisitor`]: ../trait.MakeVisitor.html
45 pub fn new(delimiter: D, inner: V) -> Self {
46 Self { delimiter, inner }
47 }
48 }
49
50 // === impl VisitDelimited ===
51
52 impl<D, V> VisitDelimited<D, V> {
53 /// Returns a new [`Visit`] implementation that wraps `inner` so that
54 /// each formatted field is separated by the provided `delimiter`.
55 ///
56 /// [`Visit`]: https://docs.rs/tracing-core/0.1.6/tracing_core/field/trait.Visit.html
57 pub fn new(delimiter: D, inner: V) -> Self {
58 Self {
59 delimiter,
60 inner,
61 seen: false,
62 err: Ok(()),
63 }
64 }
65
66 fn delimit(&mut self)
67 where
68 V: VisitFmt,
69 D: AsRef<str>,
70 {
71 if self.err.is_err() {
72 return;
73 }
74
75 if self.seen {
76 self.err = self.inner.writer().write_str(self.delimiter.as_ref());
77 }
78
79 self.seen = true;
80 }
81 }
82
83 impl<D, V> Visit for VisitDelimited<D, V>
84 where
85 V: VisitFmt,
86 D: AsRef<str>,
87 {
88 fn record_i64(&mut self, field: &Field, value: i64) {
89 self.delimit();
90 self.inner.record_i64(field, value);
91 }
92
93 fn record_u64(&mut self, field: &Field, value: u64) {
94 self.delimit();
95 self.inner.record_u64(field, value);
96 }
97
98 fn record_bool(&mut self, field: &Field, value: bool) {
99 self.delimit();
100 self.inner.record_bool(field, value);
101 }
102
103 fn record_str(&mut self, field: &Field, value: &str) {
104 self.delimit();
105 self.inner.record_str(field, value);
106 }
107
108 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
109 self.delimit();
110 self.inner.record_debug(field, value);
111 }
112 }
113
114 impl<D, V> VisitOutput<fmt::Result> for VisitDelimited<D, V>
115 where
116 V: VisitFmt,
117 D: AsRef<str>,
118 {
119 fn finish(self) -> fmt::Result {
120 self.err?;
121 self.inner.finish()
122 }
123 }
124
125 impl<D, V> VisitFmt for VisitDelimited<D, V>
126 where
127 V: VisitFmt,
128 D: AsRef<str>,
129 {
130 fn writer(&mut self) -> &mut dyn fmt::Write {
131 self.inner.writer()
132 }
133 }
134
135 #[cfg(test)]
136 #[cfg(all(test, feature = "alloc"))]
137 mod test {
138 use super::*;
139 use crate::field::test_util::*;
140
141 #[test]
142 fn delimited_visitor() {
143 let mut s = String::new();
144 let visitor = DebugVisitor::new(&mut s);
145 let mut visitor = VisitDelimited::new(", ", visitor);
146
147 TestAttrs1::with(|attrs| attrs.record(&mut visitor));
148 visitor.finish().unwrap();
149
150 assert_eq!(
151 s.as_str(),
152 "question=\"life, the universe, and everything\", tricky=true, can_you_do_it=true"
153 );
154 }
155
156 #[test]
157 fn delimited_new_visitor() {
158 let make = Delimited::new("; ", MakeDebug);
159
160 TestAttrs1::with(|attrs| {
161 let mut s = String::new();
162 {
163 let mut v = make.make_visitor(&mut s);
164 attrs.record(&mut v);
165 }
166 assert_eq!(
167 s.as_str(),
168 "question=\"life, the universe, and everything\"; tricky=true; can_you_do_it=true"
169 );
170 });
171
172 TestAttrs2::with(|attrs| {
173 let mut s = String::new();
174 {
175 let mut v = make.make_visitor(&mut s);
176 attrs.record(&mut v);
177 }
178 assert_eq!(
179 s.as_str(),
180 "question=None; question.answer=42; tricky=true; can_you_do_it=false"
181 );
182 });
183 }
184 }