1 //! Structured values.
2 
3 use std::fmt;
4 
5 extern crate value_bag;
6 
7 #[cfg(feature = "kv_unstable_sval")]
8 extern crate sval;
9 
10 #[cfg(feature = "kv_unstable_serde")]
11 extern crate serde;
12 
13 use self::value_bag::ValueBag;
14 
15 pub use kv::Error;
16 
17 /// A type that can be converted into a [`Value`](struct.Value.html).
18 pub trait ToValue {
19     /// Perform the conversion.
to_value(&self) -> Value20     fn to_value(&self) -> Value;
21 }
22 
23 impl<'a, T> ToValue for &'a T
24 where
25     T: ToValue + ?Sized,
26 {
to_value(&self) -> Value27     fn to_value(&self) -> Value {
28         (**self).to_value()
29     }
30 }
31 
32 impl<'v> ToValue for Value<'v> {
to_value(&self) -> Value33     fn to_value(&self) -> Value {
34         Value {
35             inner: self.inner.clone(),
36         }
37     }
38 }
39 
40 /// A value in a structured key-value pair.
41 ///
42 /// # Capturing values
43 ///
44 /// There are a few ways to capture a value:
45 ///
46 /// - Using the `Value::capture_*` methods.
47 /// - Using the `Value::from_*` methods.
48 /// - Using the `ToValue` trait.
49 /// - Using the standard `From` trait.
50 ///
51 /// ## Using the `Value::capture_*` methods
52 ///
53 /// `Value` offers a few constructor methods that capture values of different kinds.
54 /// These methods require a `T: 'static` to support downcasting.
55 ///
56 /// ```
57 /// use log::kv::Value;
58 ///
59 /// let value = Value::capture_debug(&42i32);
60 ///
61 /// assert_eq!(Some(42), value.to_i64());
62 /// ```
63 ///
64 /// ## Using the `Value::from_*` methods
65 ///
66 /// `Value` offers a few constructor methods that capture values of different kinds.
67 /// These methods don't require `T: 'static`, but can't support downcasting.
68 ///
69 /// ```
70 /// use log::kv::Value;
71 ///
72 /// let value = Value::from_debug(&42i32);
73 ///
74 /// assert_eq!(None, value.to_i64());
75 /// ```
76 ///
77 /// ## Using the `ToValue` trait
78 ///
79 /// The `ToValue` trait can be used to capture values generically.
80 /// It's the bound used by `Source`.
81 ///
82 /// ```
83 /// # use log::kv::ToValue;
84 /// let value = 42i32.to_value();
85 ///
86 /// assert_eq!(Some(42), value.to_i64());
87 /// ```
88 ///
89 /// ```
90 /// # use std::fmt::Debug;
91 /// use log::kv::ToValue;
92 ///
93 /// let value = (&42i32 as &dyn Debug).to_value();
94 ///
95 /// assert_eq!(None, value.to_i64());
96 /// ```
97 ///
98 /// ## Using the standard `From` trait
99 ///
100 /// Standard types that implement `ToValue` also implement `From`.
101 ///
102 /// ```
103 /// use log::kv::Value;
104 ///
105 /// let value = Value::from(42i32);
106 ///
107 /// assert_eq!(Some(42), value.to_i64());
108 /// ```
109 pub struct Value<'v> {
110     inner: ValueBag<'v>,
111 }
112 
113 impl<'v> Value<'v> {
114     /// Get a value from a type implementing `ToValue`.
from_any<T>(value: &'v T) -> Self where T: ToValue,115     pub fn from_any<T>(value: &'v T) -> Self
116     where
117         T: ToValue,
118     {
119         value.to_value()
120     }
121 
122     /// Get a value from a type implementing `std::fmt::Debug`.
capture_debug<T>(value: &'v T) -> Self where T: fmt::Debug + 'static,123     pub fn capture_debug<T>(value: &'v T) -> Self
124     where
125         T: fmt::Debug + 'static,
126     {
127         Value {
128             inner: ValueBag::capture_debug(value),
129         }
130     }
131 
132     /// Get a value from a type implementing `std::fmt::Display`.
capture_display<T>(value: &'v T) -> Self where T: fmt::Display + 'static,133     pub fn capture_display<T>(value: &'v T) -> Self
134     where
135         T: fmt::Display + 'static,
136     {
137         Value {
138             inner: ValueBag::capture_display(value),
139         }
140     }
141 
142     /// Get a value from an error.
143     #[cfg(feature = "kv_unstable_std")]
capture_error<T>(err: &'v T) -> Self where T: std::error::Error + 'static,144     pub fn capture_error<T>(err: &'v T) -> Self
145     where
146         T: std::error::Error + 'static,
147     {
148         Value {
149             inner: ValueBag::capture_error(err),
150         }
151     }
152 
153     #[cfg(feature = "kv_unstable_serde")]
154     /// Get a value from a type implementing `serde::Serialize`.
capture_serde<T>(value: &'v T) -> Self where T: self::serde::Serialize + 'static,155     pub fn capture_serde<T>(value: &'v T) -> Self
156     where
157         T: self::serde::Serialize + 'static,
158     {
159         Value {
160             inner: ValueBag::capture_serde1(value),
161         }
162     }
163 
164     /// Get a value from a type implementing `sval::value::Value`.
165     #[cfg(feature = "kv_unstable_sval")]
capture_sval<T>(value: &'v T) -> Self where T: self::sval::value::Value + 'static,166     pub fn capture_sval<T>(value: &'v T) -> Self
167     where
168         T: self::sval::value::Value + 'static,
169     {
170         Value {
171             inner: ValueBag::capture_sval1(value),
172         }
173     }
174 
175     /// Get a value from a type implementing `std::fmt::Debug`.
from_debug<T>(value: &'v T) -> Self where T: fmt::Debug,176     pub fn from_debug<T>(value: &'v T) -> Self
177     where
178         T: fmt::Debug,
179     {
180         Value {
181             inner: ValueBag::from_debug(value),
182         }
183     }
184 
185     /// Get a value from a type implementing `std::fmt::Display`.
from_display<T>(value: &'v T) -> Self where T: fmt::Display,186     pub fn from_display<T>(value: &'v T) -> Self
187     where
188         T: fmt::Display,
189     {
190         Value {
191             inner: ValueBag::from_display(value),
192         }
193     }
194 
195     /// Get a value from a type implementing `serde::Serialize`.
196     #[cfg(feature = "kv_unstable_serde")]
from_serde<T>(value: &'v T) -> Self where T: self::serde::Serialize,197     pub fn from_serde<T>(value: &'v T) -> Self
198     where
199         T: self::serde::Serialize,
200     {
201         Value {
202             inner: ValueBag::from_serde1(value),
203         }
204     }
205 
206     /// Get a value from a type implementing `sval::value::Value`.
207     #[cfg(feature = "kv_unstable_sval")]
from_sval<T>(value: &'v T) -> Self where T: self::sval::value::Value,208     pub fn from_sval<T>(value: &'v T) -> Self
209     where
210         T: self::sval::value::Value,
211     {
212         Value {
213             inner: ValueBag::from_sval1(value),
214         }
215     }
216 
217     /// Get a value from a dynamic `std::fmt::Debug`.
from_dyn_debug(value: &'v dyn fmt::Debug) -> Self218     pub fn from_dyn_debug(value: &'v dyn fmt::Debug) -> Self {
219         Value {
220             inner: ValueBag::from_dyn_debug(value),
221         }
222     }
223 
224     /// Get a value from a dynamic `std::fmt::Display`.
from_dyn_display(value: &'v dyn fmt::Display) -> Self225     pub fn from_dyn_display(value: &'v dyn fmt::Display) -> Self {
226         Value {
227             inner: ValueBag::from_dyn_display(value),
228         }
229     }
230 
231     /// Get a value from a dynamic error.
232     #[cfg(feature = "kv_unstable_std")]
from_dyn_error(err: &'v (dyn std::error::Error + 'static)) -> Self233     pub fn from_dyn_error(err: &'v (dyn std::error::Error + 'static)) -> Self {
234         Value {
235             inner: ValueBag::from_dyn_error(err),
236         }
237     }
238 
239     /// Get a value from a type implementing `sval::value::Value`.
240     #[cfg(feature = "kv_unstable_sval")]
from_dyn_sval(value: &'v dyn self::sval::value::Value) -> Self241     pub fn from_dyn_sval(value: &'v dyn self::sval::value::Value) -> Self {
242         Value {
243             inner: ValueBag::from_dyn_sval1(value),
244         }
245     }
246 
247     /// Get a value from an internal primitive.
from_value_bag<T>(value: T) -> Self where T: Into<ValueBag<'v>>,248     fn from_value_bag<T>(value: T) -> Self
249     where
250         T: Into<ValueBag<'v>>,
251     {
252         Value {
253             inner: value.into(),
254         }
255     }
256 
257     /// Check whether this value can be downcast to `T`.
is<T: 'static>(&self) -> bool258     pub fn is<T: 'static>(&self) -> bool {
259         self.inner.is::<T>()
260     }
261 
262     /// Try downcast this value to `T`.
downcast_ref<T: 'static>(&self) -> Option<&T>263     pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
264         self.inner.downcast_ref::<T>()
265     }
266 }
267 
268 impl<'v> fmt::Debug for Value<'v> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result269     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
270         fmt::Debug::fmt(&self.inner, f)
271     }
272 }
273 
274 impl<'v> fmt::Display for Value<'v> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result275     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
276         fmt::Display::fmt(&self.inner, f)
277     }
278 }
279 
280 impl ToValue for dyn fmt::Debug {
to_value(&self) -> Value281     fn to_value(&self) -> Value {
282         Value::from_dyn_debug(self)
283     }
284 }
285 
286 impl ToValue for dyn fmt::Display {
to_value(&self) -> Value287     fn to_value(&self) -> Value {
288         Value::from_dyn_display(self)
289     }
290 }
291 
292 #[cfg(feature = "kv_unstable_std")]
293 impl ToValue for dyn std::error::Error + 'static {
to_value(&self) -> Value294     fn to_value(&self) -> Value {
295         Value::from_dyn_error(self)
296     }
297 }
298 
299 #[cfg(feature = "kv_unstable_serde")]
300 impl<'v> self::serde::Serialize for Value<'v> {
serialize<S>(&self, s: S) -> Result<S::Ok, S::Error> where S: self::serde::Serializer,301     fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
302     where
303         S: self::serde::Serializer,
304     {
305         self.inner.serialize(s)
306     }
307 }
308 
309 #[cfg(feature = "kv_unstable_sval")]
310 impl<'v> self::sval::value::Value for Value<'v> {
stream(&self, stream: &mut self::sval::value::Stream) -> self::sval::value::Result311     fn stream(&self, stream: &mut self::sval::value::Stream) -> self::sval::value::Result {
312         self::sval::value::Value::stream(&self.inner, stream)
313     }
314 }
315 
316 #[cfg(feature = "kv_unstable_sval")]
317 impl ToValue for dyn self::sval::value::Value {
to_value(&self) -> Value318     fn to_value(&self) -> Value {
319         Value::from_dyn_sval(self)
320     }
321 }
322 
323 impl ToValue for str {
to_value(&self) -> Value324     fn to_value(&self) -> Value {
325         Value::from(self)
326     }
327 }
328 
329 impl<'v> From<&'v str> for Value<'v> {
from(value: &'v str) -> Self330     fn from(value: &'v str) -> Self {
331         Value::from_value_bag(value)
332     }
333 }
334 
335 impl ToValue for () {
to_value(&self) -> Value336     fn to_value(&self) -> Value {
337         Value::from_value_bag(())
338     }
339 }
340 
341 impl<T> ToValue for Option<T>
342 where
343     T: ToValue,
344 {
to_value(&self) -> Value345     fn to_value(&self) -> Value {
346         match *self {
347             Some(ref value) => value.to_value(),
348             None => Value::from_value_bag(()),
349         }
350     }
351 }
352 
353 macro_rules! impl_to_value_primitive {
354     ($($into_ty:ty,)*) => {
355         $(
356             impl ToValue for $into_ty {
357                 fn to_value(&self) -> Value {
358                     Value::from(*self)
359                 }
360             }
361 
362             impl<'v> From<$into_ty> for Value<'v> {
363                 fn from(value: $into_ty) -> Self {
364                     Value::from_value_bag(value)
365                 }
366             }
367         )*
368     };
369 }
370 
371 macro_rules! impl_value_to_primitive {
372     ($(#[doc = $doc:tt] $into_name:ident -> $into_ty:ty,)*) => {
373         impl<'v> Value<'v> {
374             $(
375                 #[doc = $doc]
376                 pub fn $into_name(&self) -> Option<$into_ty> {
377                     self.inner.$into_name()
378                 }
379             )*
380         }
381     }
382 }
383 
384 impl_to_value_primitive![
385     usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64, char, bool,
386 ];
387 
388 impl_value_to_primitive![
389     #[doc = "Try convert this value into a `u64`."]
390     to_u64 -> u64,
391     #[doc = "Try convert this value into a `i64`."]
392     to_i64 -> i64,
393     #[doc = "Try convert this value into a `u128`."]
394     to_u128 -> u128,
395     #[doc = "Try convert this value into a `i128`."]
396     to_i128 -> i128,
397     #[doc = "Try convert this value into a `f64`."]
398     to_f64 -> f64,
399     #[doc = "Try convert this value into a `char`."]
400     to_char -> char,
401     #[doc = "Try convert this value into a `bool`."]
402     to_bool -> bool,
403 ];
404 
405 impl<'v> Value<'v> {
406     /// Try convert this value into an error.
407     #[cfg(feature = "kv_unstable_std")]
to_borrowed_error(&self) -> Option<&(dyn std::error::Error + 'static)>408     pub fn to_borrowed_error(&self) -> Option<&(dyn std::error::Error + 'static)> {
409         self.inner.to_borrowed_error()
410     }
411 
412     /// Try convert this value into a borrowed string.
to_borrowed_str(&self) -> Option<&str>413     pub fn to_borrowed_str(&self) -> Option<&str> {
414         self.inner.to_borrowed_str()
415     }
416 }
417 
418 #[cfg(feature = "kv_unstable_std")]
419 mod std_support {
420     use super::*;
421 
422     use std::borrow::Cow;
423 
424     impl<T> ToValue for Box<T>
425     where
426         T: ToValue + ?Sized,
427     {
to_value(&self) -> Value428         fn to_value(&self) -> Value {
429             (**self).to_value()
430         }
431     }
432 
433     impl ToValue for String {
to_value(&self) -> Value434         fn to_value(&self) -> Value {
435             Value::from(&**self)
436         }
437     }
438 
439     impl<'v> ToValue for Cow<'v, str> {
to_value(&self) -> Value440         fn to_value(&self) -> Value {
441             Value::from(&**self)
442         }
443     }
444 
445     impl<'v> Value<'v> {
446         /// Try convert this value into a string.
to_str(&self) -> Option<Cow<str>>447         pub fn to_str(&self) -> Option<Cow<str>> {
448             self.inner.to_str()
449         }
450     }
451 }
452 
453 #[cfg(test)]
454 pub(crate) mod tests {
455     use super::*;
456 
457     pub(crate) use super::value_bag::test::Token;
458 
459     impl<'v> Value<'v> {
to_token(&self) -> Token460         pub(crate) fn to_token(&self) -> Token {
461             self.inner.to_token()
462         }
463     }
464 
unsigned() -> impl Iterator<Item = Value<'static>>465     fn unsigned() -> impl Iterator<Item = Value<'static>> {
466         vec![
467             Value::from(8u8),
468             Value::from(16u16),
469             Value::from(32u32),
470             Value::from(64u64),
471             Value::from(1usize),
472         ]
473         .into_iter()
474     }
475 
signed() -> impl Iterator<Item = Value<'static>>476     fn signed() -> impl Iterator<Item = Value<'static>> {
477         vec![
478             Value::from(-8i8),
479             Value::from(-16i16),
480             Value::from(-32i32),
481             Value::from(-64i64),
482             Value::from(-1isize),
483         ]
484         .into_iter()
485     }
486 
float() -> impl Iterator<Item = Value<'static>>487     fn float() -> impl Iterator<Item = Value<'static>> {
488         vec![Value::from(32.32f32), Value::from(64.64f64)].into_iter()
489     }
490 
bool() -> impl Iterator<Item = Value<'static>>491     fn bool() -> impl Iterator<Item = Value<'static>> {
492         vec![Value::from(true), Value::from(false)].into_iter()
493     }
494 
str() -> impl Iterator<Item = Value<'static>>495     fn str() -> impl Iterator<Item = Value<'static>> {
496         vec![Value::from("a string"), Value::from("a loong string")].into_iter()
497     }
498 
char() -> impl Iterator<Item = Value<'static>>499     fn char() -> impl Iterator<Item = Value<'static>> {
500         vec![Value::from('a'), Value::from('⛰')].into_iter()
501     }
502 
503     #[test]
test_capture_fmt()504     fn test_capture_fmt() {
505         assert_eq!(Some(42u64), Value::capture_display(&42).to_u64());
506         assert_eq!(Some(42u64), Value::capture_debug(&42).to_u64());
507 
508         assert!(Value::from_display(&42).to_u64().is_none());
509         assert!(Value::from_debug(&42).to_u64().is_none());
510     }
511 
512     #[cfg(feature = "kv_unstable_std")]
513     #[test]
test_capture_error()514     fn test_capture_error() {
515         let err = std::io::Error::from(std::io::ErrorKind::Other);
516 
517         assert!(Value::capture_error(&err).to_borrowed_error().is_some());
518         assert!(Value::from_dyn_error(&err).to_borrowed_error().is_some());
519     }
520 
521     #[cfg(feature = "kv_unstable_serde")]
522     #[test]
test_capture_serde()523     fn test_capture_serde() {
524         assert_eq!(Some(42u64), Value::capture_serde(&42).to_u64());
525 
526         assert_eq!(Some(42u64), Value::from_serde(&42).to_u64());
527     }
528 
529     #[cfg(feature = "kv_unstable_sval")]
530     #[test]
test_capture_sval()531     fn test_capture_sval() {
532         assert_eq!(Some(42u64), Value::capture_sval(&42).to_u64());
533 
534         assert_eq!(Some(42u64), Value::from_sval(&42).to_u64());
535     }
536 
537     #[test]
test_to_value_display()538     fn test_to_value_display() {
539         assert_eq!(42u64.to_value().to_string(), "42");
540         assert_eq!(42i64.to_value().to_string(), "42");
541         assert_eq!(42.01f64.to_value().to_string(), "42.01");
542         assert_eq!(true.to_value().to_string(), "true");
543         assert_eq!('a'.to_value().to_string(), "a");
544         assert_eq!("a loong string".to_value().to_string(), "a loong string");
545         assert_eq!(Some(true).to_value().to_string(), "true");
546         assert_eq!(().to_value().to_string(), "None");
547         assert_eq!(Option::None::<bool>.to_value().to_string(), "None");
548     }
549 
550     #[test]
test_to_value_structured()551     fn test_to_value_structured() {
552         assert_eq!(42u64.to_value().to_token(), Token::U64(42));
553         assert_eq!(42i64.to_value().to_token(), Token::I64(42));
554         assert_eq!(42.01f64.to_value().to_token(), Token::F64(42.01));
555         assert_eq!(true.to_value().to_token(), Token::Bool(true));
556         assert_eq!('a'.to_value().to_token(), Token::Char('a'));
557         assert_eq!(
558             "a loong string".to_value().to_token(),
559             Token::Str("a loong string".into())
560         );
561         assert_eq!(Some(true).to_value().to_token(), Token::Bool(true));
562         assert_eq!(().to_value().to_token(), Token::None);
563         assert_eq!(Option::None::<bool>.to_value().to_token(), Token::None);
564     }
565 
566     #[test]
test_to_number()567     fn test_to_number() {
568         for v in unsigned() {
569             assert!(v.to_u64().is_some());
570             assert!(v.to_i64().is_some());
571         }
572 
573         for v in signed() {
574             assert!(v.to_i64().is_some());
575         }
576 
577         for v in unsigned().chain(signed()).chain(float()) {
578             assert!(v.to_f64().is_some());
579         }
580 
581         for v in bool().chain(str()).chain(char()) {
582             assert!(v.to_u64().is_none());
583             assert!(v.to_i64().is_none());
584             assert!(v.to_f64().is_none());
585         }
586     }
587 
588     #[test]
test_to_str()589     fn test_to_str() {
590         for v in str() {
591             assert!(v.to_borrowed_str().is_some());
592 
593             #[cfg(feature = "kv_unstable_std")]
594             assert!(v.to_str().is_some());
595         }
596 
597         let short_lived = String::from("short lived");
598         let v = Value::from(&*short_lived);
599 
600         assert!(v.to_borrowed_str().is_some());
601 
602         #[cfg(feature = "kv_unstable_std")]
603         assert!(v.to_str().is_some());
604 
605         for v in unsigned().chain(signed()).chain(float()).chain(bool()) {
606             assert!(v.to_borrowed_str().is_none());
607 
608             #[cfg(feature = "kv_unstable_std")]
609             assert!(v.to_str().is_none());
610         }
611     }
612 
613     #[test]
test_to_bool()614     fn test_to_bool() {
615         for v in bool() {
616             assert!(v.to_bool().is_some());
617         }
618 
619         for v in unsigned()
620             .chain(signed())
621             .chain(float())
622             .chain(str())
623             .chain(char())
624         {
625             assert!(v.to_bool().is_none());
626         }
627     }
628 
629     #[test]
test_to_char()630     fn test_to_char() {
631         for v in char() {
632             assert!(v.to_char().is_some());
633         }
634 
635         for v in unsigned()
636             .chain(signed())
637             .chain(float())
638             .chain(str())
639             .chain(bool())
640         {
641             assert!(v.to_char().is_none());
642         }
643     }
644 
645     #[test]
test_downcast_ref()646     fn test_downcast_ref() {
647         #[derive(Debug)]
648         struct Foo(u64);
649 
650         let v = Value::capture_debug(&Foo(42));
651 
652         assert!(v.is::<Foo>());
653         assert_eq!(42u64, v.downcast_ref::<Foo>().expect("invalid downcast").0);
654     }
655 }
656