xref: /third_party/rust/crates/log/src/kv/value.rs (revision 2d8ae3ab)
1//! Structured values.
2
3use std::fmt;
4
5extern crate value_bag;
6
7#[cfg(feature = "kv_unstable_sval")]
8extern crate sval;
9
10#[cfg(feature = "kv_unstable_serde")]
11extern crate serde;
12
13use self::value_bag::ValueBag;
14
15pub use kv::Error;
16
17/// A type that can be converted into a [`Value`](struct.Value.html).
18pub trait ToValue {
19    /// Perform the conversion.
20    fn to_value(&self) -> Value;
21}
22
23impl<'a, T> ToValue for &'a T
24where
25    T: ToValue + ?Sized,
26{
27    fn to_value(&self) -> Value {
28        (**self).to_value()
29    }
30}
31
32impl<'v> ToValue for Value<'v> {
33    fn to_value(&self) -> Value {
34        Value {
35            inner: self.inner.clone(),
36        }
37    }
38}
39
40/// Get a value from a type implementing `std::fmt::Debug`.
41#[macro_export]
42macro_rules! as_debug {
43    ($capture:expr) => {
44        $crate::kv::Value::from_debug(&$capture)
45    };
46}
47
48/// Get a value from a type implementing `std::fmt::Display`.
49#[macro_export]
50macro_rules! as_display {
51    ($capture:expr) => {
52        $crate::kv::Value::from_display(&$capture)
53    };
54}
55
56/// Get a value from an error.
57#[cfg(feature = "kv_unstable_std")]
58#[macro_export]
59macro_rules! as_error {
60    ($capture:expr) => {
61        $crate::kv::Value::from_dyn_error(&$capture)
62    };
63}
64
65#[cfg(feature = "kv_unstable_serde")]
66/// Get a value from a type implementing `serde::Serialize`.
67#[macro_export]
68macro_rules! as_serde {
69    ($capture:expr) => {
70        $crate::kv::Value::from_serde(&$capture)
71    };
72}
73
74/// Get a value from a type implementing `sval::value::Value`.
75#[cfg(feature = "kv_unstable_sval")]
76#[macro_export]
77macro_rules! as_sval {
78    ($capture:expr) => {
79        $crate::kv::Value::from_sval(&$capture)
80    };
81}
82
83/// A value in a structured key-value pair.
84///
85/// # Capturing values
86///
87/// There are a few ways to capture a value:
88///
89/// - Using the `Value::capture_*` methods.
90/// - Using the `Value::from_*` methods.
91/// - Using the `ToValue` trait.
92/// - Using the standard `From` trait.
93///
94/// ## Using the `Value::capture_*` methods
95///
96/// `Value` offers a few constructor methods that capture values of different kinds.
97/// These methods require a `T: 'static` to support downcasting.
98///
99/// ```
100/// use log::kv::Value;
101///
102/// let value = Value::capture_debug(&42i32);
103///
104/// assert_eq!(Some(42), value.to_i64());
105/// ```
106///
107/// ## Using the `Value::from_*` methods
108///
109/// `Value` offers a few constructor methods that capture values of different kinds.
110/// These methods don't require `T: 'static`, but can't support downcasting.
111///
112/// ```
113/// use log::kv::Value;
114///
115/// let value = Value::from_debug(&42i32);
116///
117/// assert_eq!(None, value.to_i64());
118/// ```
119///
120/// ## Using the `ToValue` trait
121///
122/// The `ToValue` trait can be used to capture values generically.
123/// It's the bound used by `Source`.
124///
125/// ```
126/// # use log::kv::ToValue;
127/// let value = 42i32.to_value();
128///
129/// assert_eq!(Some(42), value.to_i64());
130/// ```
131///
132/// ```
133/// # use std::fmt::Debug;
134/// use log::kv::ToValue;
135///
136/// let value = (&42i32 as &dyn Debug).to_value();
137///
138/// assert_eq!(None, value.to_i64());
139/// ```
140///
141/// ## Using the standard `From` trait
142///
143/// Standard types that implement `ToValue` also implement `From`.
144///
145/// ```
146/// use log::kv::Value;
147///
148/// let value = Value::from(42i32);
149///
150/// assert_eq!(Some(42), value.to_i64());
151/// ```
152pub struct Value<'v> {
153    inner: ValueBag<'v>,
154}
155
156impl<'v> Value<'v> {
157    /// Get a value from a type implementing `ToValue`.
158    pub fn from_any<T>(value: &'v T) -> Self
159    where
160        T: ToValue,
161    {
162        value.to_value()
163    }
164
165    /// Get a value from a type implementing `std::fmt::Debug`.
166    pub fn capture_debug<T>(value: &'v T) -> Self
167    where
168        T: fmt::Debug + 'static,
169    {
170        Value {
171            inner: ValueBag::capture_debug(value),
172        }
173    }
174
175    /// Get a value from a type implementing `std::fmt::Display`.
176    pub fn capture_display<T>(value: &'v T) -> Self
177    where
178        T: fmt::Display + 'static,
179    {
180        Value {
181            inner: ValueBag::capture_display(value),
182        }
183    }
184
185    /// Get a value from an error.
186    #[cfg(feature = "kv_unstable_std")]
187    pub fn capture_error<T>(err: &'v T) -> Self
188    where
189        T: std::error::Error + 'static,
190    {
191        Value {
192            inner: ValueBag::capture_error(err),
193        }
194    }
195
196    #[cfg(feature = "kv_unstable_serde")]
197    /// Get a value from a type implementing `serde::Serialize`.
198    pub fn capture_serde<T>(value: &'v T) -> Self
199    where
200        T: self::serde::Serialize + 'static,
201    {
202        Value {
203            inner: ValueBag::capture_serde1(value),
204        }
205    }
206
207    /// Get a value from a type implementing `sval::value::Value`.
208    #[cfg(feature = "kv_unstable_sval")]
209    pub fn capture_sval<T>(value: &'v T) -> Self
210    where
211        T: self::sval::value::Value + 'static,
212    {
213        Value {
214            inner: ValueBag::capture_sval1(value),
215        }
216    }
217
218    /// Get a value from a type implementing `std::fmt::Debug`.
219    pub fn from_debug<T>(value: &'v T) -> Self
220    where
221        T: fmt::Debug,
222    {
223        Value {
224            inner: ValueBag::from_debug(value),
225        }
226    }
227
228    /// Get a value from a type implementing `std::fmt::Display`.
229    pub fn from_display<T>(value: &'v T) -> Self
230    where
231        T: fmt::Display,
232    {
233        Value {
234            inner: ValueBag::from_display(value),
235        }
236    }
237
238    /// Get a value from a type implementing `serde::Serialize`.
239    #[cfg(feature = "kv_unstable_serde")]
240    pub fn from_serde<T>(value: &'v T) -> Self
241    where
242        T: self::serde::Serialize,
243    {
244        Value {
245            inner: ValueBag::from_serde1(value),
246        }
247    }
248
249    /// Get a value from a type implementing `sval::value::Value`.
250    #[cfg(feature = "kv_unstable_sval")]
251    pub fn from_sval<T>(value: &'v T) -> Self
252    where
253        T: self::sval::value::Value,
254    {
255        Value {
256            inner: ValueBag::from_sval1(value),
257        }
258    }
259
260    /// Get a value from a dynamic `std::fmt::Debug`.
261    pub fn from_dyn_debug(value: &'v dyn fmt::Debug) -> Self {
262        Value {
263            inner: ValueBag::from_dyn_debug(value),
264        }
265    }
266
267    /// Get a value from a dynamic `std::fmt::Display`.
268    pub fn from_dyn_display(value: &'v dyn fmt::Display) -> Self {
269        Value {
270            inner: ValueBag::from_dyn_display(value),
271        }
272    }
273
274    /// Get a value from a dynamic error.
275    #[cfg(feature = "kv_unstable_std")]
276    pub fn from_dyn_error(err: &'v (dyn std::error::Error + 'static)) -> Self {
277        Value {
278            inner: ValueBag::from_dyn_error(err),
279        }
280    }
281
282    /// Get a value from a type implementing `sval::value::Value`.
283    #[cfg(feature = "kv_unstable_sval")]
284    pub fn from_dyn_sval(value: &'v dyn self::sval::value::Value) -> Self {
285        Value {
286            inner: ValueBag::from_dyn_sval1(value),
287        }
288    }
289
290    /// Get a value from an internal primitive.
291    fn from_value_bag<T>(value: T) -> Self
292    where
293        T: Into<ValueBag<'v>>,
294    {
295        Value {
296            inner: value.into(),
297        }
298    }
299
300    /// Check whether this value can be downcast to `T`.
301    pub fn is<T: 'static>(&self) -> bool {
302        self.inner.is::<T>()
303    }
304
305    /// Try downcast this value to `T`.
306    pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
307        self.inner.downcast_ref::<T>()
308    }
309
310    /// Inspect this value using a simple visitor.
311    pub fn visit(&self, visitor: impl Visit<'v>) -> Result<(), Error> {
312        struct Visitor<V>(V);
313
314        impl<'v, V> value_bag::visit::Visit<'v> for Visitor<V>
315        where
316            V: Visit<'v>,
317        {
318            fn visit_any(&mut self, value: ValueBag) -> Result<(), value_bag::Error> {
319                self.0
320                    .visit_any(Value { inner: value })
321                    .map_err(Error::into_value)
322            }
323
324            fn visit_u64(&mut self, value: u64) -> Result<(), value_bag::Error> {
325                self.0.visit_u64(value).map_err(Error::into_value)
326            }
327
328            fn visit_i64(&mut self, value: i64) -> Result<(), value_bag::Error> {
329                self.0.visit_i64(value).map_err(Error::into_value)
330            }
331
332            fn visit_u128(&mut self, value: u128) -> Result<(), value_bag::Error> {
333                self.0.visit_u128(value).map_err(Error::into_value)
334            }
335
336            fn visit_i128(&mut self, value: i128) -> Result<(), value_bag::Error> {
337                self.0.visit_i128(value).map_err(Error::into_value)
338            }
339
340            fn visit_f64(&mut self, value: f64) -> Result<(), value_bag::Error> {
341                self.0.visit_f64(value).map_err(Error::into_value)
342            }
343
344            fn visit_bool(&mut self, value: bool) -> Result<(), value_bag::Error> {
345                self.0.visit_bool(value).map_err(Error::into_value)
346            }
347
348            fn visit_str(&mut self, value: &str) -> Result<(), value_bag::Error> {
349                self.0.visit_str(value).map_err(Error::into_value)
350            }
351
352            fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), value_bag::Error> {
353                self.0.visit_borrowed_str(value).map_err(Error::into_value)
354            }
355
356            fn visit_char(&mut self, value: char) -> Result<(), value_bag::Error> {
357                self.0.visit_char(value).map_err(Error::into_value)
358            }
359
360            #[cfg(feature = "kv_unstable_std")]
361            fn visit_error(
362                &mut self,
363                err: &(dyn std::error::Error + 'static),
364            ) -> Result<(), value_bag::Error> {
365                self.0.visit_error(err).map_err(Error::into_value)
366            }
367
368            #[cfg(feature = "kv_unstable_std")]
369            fn visit_borrowed_error(
370                &mut self,
371                err: &'v (dyn std::error::Error + 'static),
372            ) -> Result<(), value_bag::Error> {
373                self.0.visit_borrowed_error(err).map_err(Error::into_value)
374            }
375        }
376
377        self.inner
378            .visit(&mut Visitor(visitor))
379            .map_err(Error::from_value)
380    }
381}
382
383impl<'v> fmt::Debug for Value<'v> {
384    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
385        fmt::Debug::fmt(&self.inner, f)
386    }
387}
388
389impl<'v> fmt::Display for Value<'v> {
390    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
391        fmt::Display::fmt(&self.inner, f)
392    }
393}
394
395impl ToValue for dyn fmt::Debug {
396    fn to_value(&self) -> Value {
397        Value::from_dyn_debug(self)
398    }
399}
400
401impl ToValue for dyn fmt::Display {
402    fn to_value(&self) -> Value {
403        Value::from_dyn_display(self)
404    }
405}
406
407#[cfg(feature = "kv_unstable_std")]
408impl ToValue for dyn std::error::Error + 'static {
409    fn to_value(&self) -> Value {
410        Value::from_dyn_error(self)
411    }
412}
413
414#[cfg(feature = "kv_unstable_serde")]
415impl<'v> self::serde::Serialize for Value<'v> {
416    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
417    where
418        S: self::serde::Serializer,
419    {
420        self.inner.serialize(s)
421    }
422}
423
424#[cfg(feature = "kv_unstable_sval")]
425impl<'v> self::sval::value::Value for Value<'v> {
426    fn stream(&self, stream: &mut self::sval::value::Stream) -> self::sval::value::Result {
427        self::sval::value::Value::stream(&self.inner, stream)
428    }
429}
430
431#[cfg(feature = "kv_unstable_sval")]
432impl ToValue for dyn self::sval::value::Value {
433    fn to_value(&self) -> Value {
434        Value::from_dyn_sval(self)
435    }
436}
437
438impl ToValue for str {
439    fn to_value(&self) -> Value {
440        Value::from(self)
441    }
442}
443
444impl ToValue for u128 {
445    fn to_value(&self) -> Value {
446        Value::from(self)
447    }
448}
449
450impl ToValue for i128 {
451    fn to_value(&self) -> Value {
452        Value::from(self)
453    }
454}
455
456impl ToValue for std::num::NonZeroU128 {
457    fn to_value(&self) -> Value {
458        Value::from(self)
459    }
460}
461
462impl ToValue for std::num::NonZeroI128 {
463    fn to_value(&self) -> Value {
464        Value::from(self)
465    }
466}
467
468impl<'v> From<&'v str> for Value<'v> {
469    fn from(value: &'v str) -> Self {
470        Value::from_value_bag(value)
471    }
472}
473
474impl<'v> From<&'v u128> for Value<'v> {
475    fn from(value: &'v u128) -> Self {
476        Value::from_value_bag(value)
477    }
478}
479
480impl<'v> From<&'v i128> for Value<'v> {
481    fn from(value: &'v i128) -> Self {
482        Value::from_value_bag(value)
483    }
484}
485
486impl<'v> From<&'v std::num::NonZeroU128> for Value<'v> {
487    fn from(v: &'v std::num::NonZeroU128) -> Value<'v> {
488        // SAFETY: `NonZeroU128` and `u128` have the same ABI
489        Value::from_value_bag(unsafe { std::mem::transmute::<&std::num::NonZeroU128, &u128>(v) })
490    }
491}
492
493impl<'v> From<&'v std::num::NonZeroI128> for Value<'v> {
494    fn from(v: &'v std::num::NonZeroI128) -> Value<'v> {
495        // SAFETY: `NonZeroI128` and `i128` have the same ABI
496        Value::from_value_bag(unsafe { std::mem::transmute::<&std::num::NonZeroI128, &i128>(v) })
497    }
498}
499
500impl ToValue for () {
501    fn to_value(&self) -> Value {
502        Value::from_value_bag(())
503    }
504}
505
506impl<T> ToValue for Option<T>
507where
508    T: ToValue,
509{
510    fn to_value(&self) -> Value {
511        match *self {
512            Some(ref value) => value.to_value(),
513            None => Value::from_value_bag(()),
514        }
515    }
516}
517
518macro_rules! impl_to_value_primitive {
519    ($($into_ty:ty,)*) => {
520        $(
521            impl ToValue for $into_ty {
522                fn to_value(&self) -> Value {
523                    Value::from(*self)
524                }
525            }
526
527            impl<'v> From<$into_ty> for Value<'v> {
528                fn from(value: $into_ty) -> Self {
529                    Value::from_value_bag(value)
530                }
531            }
532        )*
533    };
534}
535
536macro_rules! impl_to_value_nonzero_primitive {
537    ($($into_ty:ident,)*) => {
538        $(
539            impl ToValue for std::num::$into_ty {
540                fn to_value(&self) -> Value {
541                    Value::from(self.get())
542                }
543            }
544
545            impl<'v> From<std::num::$into_ty> for Value<'v> {
546                fn from(value: std::num::$into_ty) -> Self {
547                    Value::from(value.get())
548                }
549            }
550        )*
551    };
552}
553
554macro_rules! impl_value_to_primitive {
555    ($(#[doc = $doc:tt] $into_name:ident -> $into_ty:ty,)*) => {
556        impl<'v> Value<'v> {
557            $(
558                #[doc = $doc]
559                pub fn $into_name(&self) -> Option<$into_ty> {
560                    self.inner.$into_name()
561                }
562            )*
563        }
564    }
565}
566
567impl_to_value_primitive![usize, u8, u16, u32, u64, isize, i8, i16, i32, i64, f32, f64, char, bool,];
568
569#[rustfmt::skip]
570impl_to_value_nonzero_primitive![
571    NonZeroUsize, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64,
572    NonZeroIsize, NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64,
573];
574
575impl_value_to_primitive![
576    #[doc = "Try convert this value into a `u64`."]
577    to_u64 -> u64,
578    #[doc = "Try convert this value into a `i64`."]
579    to_i64 -> i64,
580    #[doc = "Try convert this value into a `u128`."]
581    to_u128 -> u128,
582    #[doc = "Try convert this value into a `i128`."]
583    to_i128 -> i128,
584    #[doc = "Try convert this value into a `f64`."]
585    to_f64 -> f64,
586    #[doc = "Try convert this value into a `char`."]
587    to_char -> char,
588    #[doc = "Try convert this value into a `bool`."]
589    to_bool -> bool,
590];
591
592impl<'v> Value<'v> {
593    /// Try convert this value into an error.
594    #[cfg(feature = "kv_unstable_std")]
595    pub fn to_borrowed_error(&self) -> Option<&(dyn std::error::Error + 'static)> {
596        self.inner.to_borrowed_error()
597    }
598
599    /// Try convert this value into a borrowed string.
600    pub fn to_borrowed_str(&self) -> Option<&str> {
601        self.inner.to_borrowed_str()
602    }
603}
604
605#[cfg(feature = "kv_unstable_std")]
606mod std_support {
607    use super::*;
608
609    use std::borrow::Cow;
610
611    impl<T> ToValue for Box<T>
612    where
613        T: ToValue + ?Sized,
614    {
615        fn to_value(&self) -> Value {
616            (**self).to_value()
617        }
618    }
619
620    impl ToValue for String {
621        fn to_value(&self) -> Value {
622            Value::from(&**self)
623        }
624    }
625
626    impl<'v> ToValue for Cow<'v, str> {
627        fn to_value(&self) -> Value {
628            Value::from(&**self)
629        }
630    }
631
632    impl<'v> Value<'v> {
633        /// Try convert this value into a string.
634        pub fn to_str(&self) -> Option<Cow<str>> {
635            self.inner.to_str()
636        }
637    }
638
639    impl<'v> From<&'v String> for Value<'v> {
640        fn from(v: &'v String) -> Self {
641            Value::from(&**v)
642        }
643    }
644}
645
646/// A visitor for a `Value`.
647pub trait Visit<'v> {
648    /// Visit a `Value`.
649    ///
650    /// This is the only required method on `Visit` and acts as a fallback for any
651    /// more specific methods that aren't overridden.
652    /// The `Value` may be formatted using its `fmt::Debug` or `fmt::Display` implementation,
653    /// or serialized using its `sval::Value` or `serde::Serialize` implementation.
654    fn visit_any(&mut self, value: Value) -> Result<(), Error>;
655
656    /// Visit an unsigned integer.
657    fn visit_u64(&mut self, value: u64) -> Result<(), Error> {
658        self.visit_any(value.into())
659    }
660
661    /// Visit a signed integer.
662    fn visit_i64(&mut self, value: i64) -> Result<(), Error> {
663        self.visit_any(value.into())
664    }
665
666    /// Visit a big unsigned integer.
667    fn visit_u128(&mut self, value: u128) -> Result<(), Error> {
668        self.visit_any((&value).into())
669    }
670
671    /// Visit a big signed integer.
672    fn visit_i128(&mut self, value: i128) -> Result<(), Error> {
673        self.visit_any((&value).into())
674    }
675
676    /// Visit a floating point.
677    fn visit_f64(&mut self, value: f64) -> Result<(), Error> {
678        self.visit_any(value.into())
679    }
680
681    /// Visit a boolean.
682    fn visit_bool(&mut self, value: bool) -> Result<(), Error> {
683        self.visit_any(value.into())
684    }
685
686    /// Visit a string.
687    fn visit_str(&mut self, value: &str) -> Result<(), Error> {
688        self.visit_any(value.into())
689    }
690
691    /// Visit a string.
692    fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), Error> {
693        self.visit_str(value)
694    }
695
696    /// Visit a Unicode character.
697    fn visit_char(&mut self, value: char) -> Result<(), Error> {
698        let mut b = [0; 4];
699        self.visit_str(&*value.encode_utf8(&mut b))
700    }
701
702    /// Visit an error.
703    #[cfg(feature = "kv_unstable_std")]
704    fn visit_error(&mut self, err: &(dyn std::error::Error + 'static)) -> Result<(), Error> {
705        self.visit_any(Value::from_dyn_error(err))
706    }
707
708    /// Visit an error.
709    #[cfg(feature = "kv_unstable_std")]
710    fn visit_borrowed_error(
711        &mut self,
712        err: &'v (dyn std::error::Error + 'static),
713    ) -> Result<(), Error> {
714        self.visit_any(Value::from_dyn_error(err))
715    }
716}
717
718impl<'a, 'v, T: ?Sized> Visit<'v> for &'a mut T
719where
720    T: Visit<'v>,
721{
722    fn visit_any(&mut self, value: Value) -> Result<(), Error> {
723        (**self).visit_any(value)
724    }
725
726    fn visit_u64(&mut self, value: u64) -> Result<(), Error> {
727        (**self).visit_u64(value)
728    }
729
730    fn visit_i64(&mut self, value: i64) -> Result<(), Error> {
731        (**self).visit_i64(value)
732    }
733
734    fn visit_u128(&mut self, value: u128) -> Result<(), Error> {
735        (**self).visit_u128(value)
736    }
737
738    fn visit_i128(&mut self, value: i128) -> Result<(), Error> {
739        (**self).visit_i128(value)
740    }
741
742    fn visit_f64(&mut self, value: f64) -> Result<(), Error> {
743        (**self).visit_f64(value)
744    }
745
746    fn visit_bool(&mut self, value: bool) -> Result<(), Error> {
747        (**self).visit_bool(value)
748    }
749
750    fn visit_str(&mut self, value: &str) -> Result<(), Error> {
751        (**self).visit_str(value)
752    }
753
754    fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), Error> {
755        (**self).visit_borrowed_str(value)
756    }
757
758    fn visit_char(&mut self, value: char) -> Result<(), Error> {
759        (**self).visit_char(value)
760    }
761
762    #[cfg(feature = "kv_unstable_std")]
763    fn visit_error(&mut self, err: &(dyn std::error::Error + 'static)) -> Result<(), Error> {
764        (**self).visit_error(err)
765    }
766
767    #[cfg(feature = "kv_unstable_std")]
768    fn visit_borrowed_error(
769        &mut self,
770        err: &'v (dyn std::error::Error + 'static),
771    ) -> Result<(), Error> {
772        (**self).visit_borrowed_error(err)
773    }
774}
775
776#[cfg(test)]
777pub(crate) mod tests {
778    use super::*;
779
780    pub(crate) use super::value_bag::test::Token;
781
782    impl<'v> Value<'v> {
783        pub(crate) fn to_token(&self) -> Token {
784            self.inner.to_token()
785        }
786    }
787
788    fn unsigned() -> impl Iterator<Item = Value<'static>> {
789        vec![
790            Value::from(8u8),
791            Value::from(16u16),
792            Value::from(32u32),
793            Value::from(64u64),
794            Value::from(1usize),
795            Value::from(std::num::NonZeroU8::new(8).unwrap()),
796            Value::from(std::num::NonZeroU16::new(16).unwrap()),
797            Value::from(std::num::NonZeroU32::new(32).unwrap()),
798            Value::from(std::num::NonZeroU64::new(64).unwrap()),
799            Value::from(std::num::NonZeroUsize::new(1).unwrap()),
800        ]
801        .into_iter()
802    }
803
804    fn signed() -> impl Iterator<Item = Value<'static>> {
805        vec![
806            Value::from(-8i8),
807            Value::from(-16i16),
808            Value::from(-32i32),
809            Value::from(-64i64),
810            Value::from(-1isize),
811            Value::from(std::num::NonZeroI8::new(-8).unwrap()),
812            Value::from(std::num::NonZeroI16::new(-16).unwrap()),
813            Value::from(std::num::NonZeroI32::new(-32).unwrap()),
814            Value::from(std::num::NonZeroI64::new(-64).unwrap()),
815            Value::from(std::num::NonZeroIsize::new(-1).unwrap()),
816        ]
817        .into_iter()
818    }
819
820    fn float() -> impl Iterator<Item = Value<'static>> {
821        vec![Value::from(32.32f32), Value::from(64.64f64)].into_iter()
822    }
823
824    fn bool() -> impl Iterator<Item = Value<'static>> {
825        vec![Value::from(true), Value::from(false)].into_iter()
826    }
827
828    fn str() -> impl Iterator<Item = Value<'static>> {
829        vec![Value::from("a string"), Value::from("a loong string")].into_iter()
830    }
831
832    fn char() -> impl Iterator<Item = Value<'static>> {
833        vec![Value::from('a'), Value::from('⛰')].into_iter()
834    }
835
836    #[test]
837    fn test_capture_fmt() {
838        assert_eq!(Some(42u64), Value::capture_display(&42).to_u64());
839        assert_eq!(Some(42u64), Value::capture_debug(&42).to_u64());
840
841        assert!(Value::from_display(&42).to_u64().is_none());
842        assert!(Value::from_debug(&42).to_u64().is_none());
843    }
844
845    #[cfg(feature = "kv_unstable_std")]
846    #[test]
847    fn test_capture_error() {
848        let err = std::io::Error::from(std::io::ErrorKind::Other);
849
850        assert!(Value::capture_error(&err).to_borrowed_error().is_some());
851        assert!(Value::from_dyn_error(&err).to_borrowed_error().is_some());
852    }
853
854    #[cfg(feature = "kv_unstable_serde")]
855    #[test]
856    fn test_capture_serde() {
857        assert_eq!(Some(42u64), Value::capture_serde(&42).to_u64());
858
859        assert_eq!(Some(42u64), Value::from_serde(&42).to_u64());
860    }
861
862    #[cfg(feature = "kv_unstable_sval")]
863    #[test]
864    fn test_capture_sval() {
865        assert_eq!(Some(42u64), Value::capture_sval(&42).to_u64());
866
867        assert_eq!(Some(42u64), Value::from_sval(&42).to_u64());
868    }
869
870    #[test]
871    fn test_to_value_display() {
872        assert_eq!(42u64.to_value().to_string(), "42");
873        assert_eq!(42i64.to_value().to_string(), "42");
874        assert_eq!(42.01f64.to_value().to_string(), "42.01");
875        assert_eq!(true.to_value().to_string(), "true");
876        assert_eq!('a'.to_value().to_string(), "a");
877        assert_eq!("a loong string".to_value().to_string(), "a loong string");
878        assert_eq!(Some(true).to_value().to_string(), "true");
879        assert_eq!(().to_value().to_string(), "None");
880        assert_eq!(Option::None::<bool>.to_value().to_string(), "None");
881    }
882
883    #[test]
884    fn test_to_value_structured() {
885        assert_eq!(42u64.to_value().to_token(), Token::U64(42));
886        assert_eq!(42i64.to_value().to_token(), Token::I64(42));
887        assert_eq!(42.01f64.to_value().to_token(), Token::F64(42.01));
888        assert_eq!(true.to_value().to_token(), Token::Bool(true));
889        assert_eq!('a'.to_value().to_token(), Token::Char('a'));
890        assert_eq!(
891            "a loong string".to_value().to_token(),
892            Token::Str("a loong string".into())
893        );
894        assert_eq!(Some(true).to_value().to_token(), Token::Bool(true));
895        assert_eq!(().to_value().to_token(), Token::None);
896        assert_eq!(Option::None::<bool>.to_value().to_token(), Token::None);
897    }
898
899    #[test]
900    fn test_to_number() {
901        for v in unsigned() {
902            assert!(v.to_u64().is_some());
903            assert!(v.to_i64().is_some());
904        }
905
906        for v in signed() {
907            assert!(v.to_i64().is_some());
908        }
909
910        for v in unsigned().chain(signed()).chain(float()) {
911            assert!(v.to_f64().is_some());
912        }
913
914        for v in bool().chain(str()).chain(char()) {
915            assert!(v.to_u64().is_none());
916            assert!(v.to_i64().is_none());
917            assert!(v.to_f64().is_none());
918        }
919    }
920
921    #[test]
922    fn test_to_str() {
923        for v in str() {
924            assert!(v.to_borrowed_str().is_some());
925
926            #[cfg(feature = "kv_unstable_std")]
927            assert!(v.to_str().is_some());
928        }
929
930        let short_lived = String::from("short lived");
931        let v = Value::from(&*short_lived);
932
933        assert!(v.to_borrowed_str().is_some());
934
935        #[cfg(feature = "kv_unstable_std")]
936        assert!(v.to_str().is_some());
937
938        for v in unsigned().chain(signed()).chain(float()).chain(bool()) {
939            assert!(v.to_borrowed_str().is_none());
940
941            #[cfg(feature = "kv_unstable_std")]
942            assert!(v.to_str().is_none());
943        }
944    }
945
946    #[test]
947    fn test_to_bool() {
948        for v in bool() {
949            assert!(v.to_bool().is_some());
950        }
951
952        for v in unsigned()
953            .chain(signed())
954            .chain(float())
955            .chain(str())
956            .chain(char())
957        {
958            assert!(v.to_bool().is_none());
959        }
960    }
961
962    #[test]
963    fn test_to_char() {
964        for v in char() {
965            assert!(v.to_char().is_some());
966        }
967
968        for v in unsigned()
969            .chain(signed())
970            .chain(float())
971            .chain(str())
972            .chain(bool())
973        {
974            assert!(v.to_char().is_none());
975        }
976    }
977
978    #[test]
979    fn test_downcast_ref() {
980        #[derive(Debug)]
981        struct Foo(u64);
982
983        let v = Value::capture_debug(&Foo(42));
984
985        assert!(v.is::<Foo>());
986        assert_eq!(42u64, v.downcast_ref::<Foo>().expect("invalid downcast").0);
987    }
988
989    #[test]
990    fn test_visit_integer() {
991        struct Extract(Option<u64>);
992
993        impl<'v> Visit<'v> for Extract {
994            fn visit_any(&mut self, value: Value) -> Result<(), Error> {
995                unimplemented!("unexpected value: {:?}", value)
996            }
997
998            fn visit_u64(&mut self, value: u64) -> Result<(), Error> {
999                self.0 = Some(value);
1000
1001                Ok(())
1002            }
1003        }
1004
1005        let mut extract = Extract(None);
1006        Value::from(42u64).visit(&mut extract).unwrap();
1007
1008        assert_eq!(Some(42), extract.0);
1009    }
1010
1011    #[test]
1012    fn test_visit_borrowed_str() {
1013        struct Extract<'v>(Option<&'v str>);
1014
1015        impl<'v> Visit<'v> for Extract<'v> {
1016            fn visit_any(&mut self, value: Value) -> Result<(), Error> {
1017                unimplemented!("unexpected value: {:?}", value)
1018            }
1019
1020            fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), Error> {
1021                self.0 = Some(value);
1022
1023                Ok(())
1024            }
1025        }
1026
1027        let mut extract = Extract(None);
1028
1029        let short_lived = String::from("A short-lived string");
1030        Value::from(&*short_lived).visit(&mut extract).unwrap();
1031
1032        assert_eq!(Some("A short-lived string"), extract.0);
1033    }
1034}
1035