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.
to_value(&self) -> Value18     fn to_value(&self) -> Value;
19 }
20 
21 impl<'a, T> ToValue for &'a T
22 where
23     T: ToValue + ?Sized,
24 {
to_value(&self) -> Value25     fn to_value(&self) -> Value {
26         (**self).to_value()
27     }
28 }
29 
30 impl<'v> ToValue for Value<'v> {
to_value(&self) -> Value31     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.
fill(&self, slot: &mut Slot) -> Result<(), Error>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 {
fill(&self, slot: &mut Slot) -> Result<(), Error>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> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result64     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
65         f.debug_struct("Slot").finish()
66     }
67 }
68 
69 impl<'a> Slot<'a> {
new(visitor: &'a mut Visitor) -> Self70     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.
fill(&mut self, value: Value) -> Result<(), Error>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`.
from_primitive(value: Primitive<'v>) -> Self99     fn from_primitive(value: Primitive<'v>) -> Self {
100         Value {
101             inner: Inner::Primitive(value),
102         }
103     }
104 
105     /// Get a value from a fillable slot.
from_fill<T>(value: &'v T) -> Self where T: Fill,106     pub fn from_fill<T>(value: &'v T) -> Self
107     where
108         T: Fill,
109     {
110         Value {
111             inner: Inner::Fill(value),
112         }
113     }
114 
visit(&self, visitor: &mut Visitor) -> Result<(), Error>115     fn visit(&self, visitor: &mut Visitor) -> Result<(), Error> {
116         self.inner.visit(visitor)
117     }
118 }
119 
120 #[cfg(test)]
121 mod tests {
122     use super::*;
123 
124     #[test]
fill_value()125     fn fill_value() {
126         struct TestFill;
127 
128         impl Fill for TestFill {
129             fn fill(&self, slot: &mut Slot) -> Result<(), Error> {
130                 let dbg: &fmt::Debug = &1;
131 
132                 slot.fill(Value::from_debug(&dbg))
133             }
134         }
135 
136         assert_eq!("1", Value::from_fill(&TestFill).to_string());
137     }
138 
139     #[test]
140     #[should_panic]
fill_multiple_times_panics()141     fn fill_multiple_times_panics() {
142         struct BadFill;
143 
144         impl Fill for BadFill {
145             fn fill(&self, slot: &mut Slot) -> Result<(), Error> {
146                 slot.fill(42.into())?;
147                 slot.fill(6789.into())?;
148 
149                 Ok(())
150             }
151         }
152 
153         let _ = Value::from_fill(&BadFill).to_string();
154     }
155 }
156