]> git.proxmox.com Git - cargo.git/blob - vendor/log/src/kv/value/mod.rs
New upstream version 0.37.0
[cargo.git] / vendor / log / src / kv / value / mod.rs
1 //! Structured values.
2
3 use std::fmt;
4
5 mod internal;
6 mod impls;
7
8 #[cfg(test)]
9 pub(in kv) mod test;
10
11 pub use kv::Error;
12
13 use self::internal::{Inner, Visitor, Primitive};
14
15 /// A type that can be converted into a [`Value`](struct.Value.html).
16 pub trait ToValue {
17 /// Perform the conversion.
18 fn to_value(&self) -> Value;
19 }
20
21 impl<'a, T> ToValue for &'a T
22 where
23 T: ToValue + ?Sized,
24 {
25 fn to_value(&self) -> Value {
26 (**self).to_value()
27 }
28 }
29
30 impl<'v> ToValue for Value<'v> {
31 fn to_value(&self) -> Value {
32 Value {
33 inner: self.inner,
34 }
35 }
36 }
37
38 /// A type that requires extra work to convert into a [`Value`](struct.Value.html).
39 ///
40 /// This trait is a more advanced initialization API than [`ToValue`](trait.ToValue.html).
41 /// It's intended for erased values coming from other logging frameworks that may need
42 /// to perform extra work to determine the concrete type to use.
43 pub trait Fill {
44 /// Fill a value.
45 fn fill(&self, slot: &mut Slot) -> Result<(), Error>;
46 }
47
48 impl<'a, T> Fill for &'a T
49 where
50 T: Fill + ?Sized,
51 {
52 fn fill(&self, slot: &mut Slot) -> Result<(), Error> {
53 (**self).fill(slot)
54 }
55 }
56
57 /// A value slot to fill using the [`Fill`](trait.Fill.html) trait.
58 pub struct Slot<'a> {
59 filled: bool,
60 visitor: &'a mut Visitor,
61 }
62
63 impl<'a> fmt::Debug for Slot<'a> {
64 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
65 f.debug_struct("Slot").finish()
66 }
67 }
68
69 impl<'a> Slot<'a> {
70 fn new(visitor: &'a mut Visitor) -> Self {
71 Slot {
72 visitor,
73 filled: false,
74 }
75 }
76
77 /// Fill the slot with a value.
78 ///
79 /// The given value doesn't need to satisfy any particular lifetime constraints.
80 ///
81 /// # Panics
82 ///
83 /// Calling `fill` more than once will panic.
84 pub fn fill(&mut self, value: Value) -> Result<(), Error> {
85 assert!(!self.filled, "the slot has already been filled");
86 self.filled = true;
87
88 value.visit(self.visitor)
89 }
90 }
91
92 /// A value in a structured key-value pair.
93 pub struct Value<'v> {
94 inner: Inner<'v>,
95 }
96
97 impl<'v> Value<'v> {
98 /// Get a value from an internal `Visit`.
99 fn from_primitive(value: Primitive<'v>) -> Self {
100 Value {
101 inner: Inner::Primitive(value),
102 }
103 }
104
105 /// Get a value from a debuggable type.
106 pub fn from_debug<T>(value: &'v T) -> Self
107 where
108 T: fmt::Debug,
109 {
110 Value {
111 inner: Inner::Debug(value),
112 }
113 }
114
115 /// Get a value from a displayable type.
116 pub fn from_display<T>(value: &'v T) -> Self
117 where
118 T: fmt::Display,
119 {
120 Value {
121 inner: Inner::Display(value),
122 }
123 }
124
125 /// Get a value from a fillable slot.
126 pub fn from_fill<T>(value: &'v T) -> Self
127 where
128 T: Fill,
129 {
130 Value {
131 inner: Inner::Fill(value),
132 }
133 }
134
135 fn visit(&self, visitor: &mut Visitor) -> Result<(), Error> {
136 self.inner.visit(visitor)
137 }
138 }
139
140 impl<'v> fmt::Debug for Value<'v> {
141 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
142 self.visit(&mut self::internal::FmtVisitor(f))?;
143
144 Ok(())
145 }
146 }
147
148 impl<'v> fmt::Display for Value<'v> {
149 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
150 self.visit(&mut self::internal::FmtVisitor(f))?;
151
152 Ok(())
153 }
154 }
155
156 #[cfg(test)]
157 mod tests {
158 use super::*;
159
160 #[test]
161 fn fill_value() {
162 struct TestFill;
163
164 impl Fill for TestFill {
165 fn fill(&self, slot: &mut Slot) -> Result<(), Error> {
166 let dbg: &fmt::Debug = &1;
167
168 slot.fill(Value::from_debug(&dbg))
169 }
170 }
171
172 assert_eq!("1", Value::from_fill(&TestFill).to_str_buf());
173 }
174
175 #[test]
176 #[should_panic]
177 fn fill_multiple_times_panics() {
178 struct BadFill;
179
180 impl Fill for BadFill {
181 fn fill(&self, slot: &mut Slot) -> Result<(), Error> {
182 slot.fill(42.into())?;
183 slot.fill(6789.into())?;
184
185 Ok(())
186 }
187 }
188
189 let _ = Value::from_fill(&BadFill).to_str_buf();
190 }
191 }