Skip to main content

log/kv/
value.rs

1//! Structured values.
2//!
3//! This module defines the [`Value`] type and supporting APIs for
4//! capturing and serializing them.
5
6use std::fmt;
7
8pub use crate::kv::Error;
9
10/// A type that can be converted into a [`Value`](struct.Value.html).
11pub trait ToValue {
12    /// Perform the conversion.
13    fn to_value(&self) -> Value<'_>;
14}
15
16impl<T> ToValue for &T
17where
18    T: ToValue + ?Sized,
19{
20    fn to_value(&self) -> Value<'_> {
21        (**self).to_value()
22    }
23}
24
25impl<'v> ToValue for Value<'v> {
26    fn to_value(&self) -> Value<'_> {
27        Value {
28            inner: self.inner.clone(),
29        }
30    }
31}
32
33/// A value in a key-value.
34///
35/// Values are an anonymous bag containing some structured datum.
36///
37/// # Capturing values
38///
39/// There are a few ways to capture a value:
40///
41/// - Using the `Value::from_*` methods.
42/// - Using the `ToValue` trait.
43/// - Using the standard `From` trait.
44///
45/// ## Using the `Value::from_*` methods
46///
47/// `Value` offers a few constructor methods that capture values of different kinds.
48///
49/// ```
50/// use log::kv::Value;
51///
52/// let value = Value::from_debug(&42i32);
53///
54/// assert_eq!(None, value.to_i64());
55/// ```
56///
57/// ## Using the `ToValue` trait
58///
59/// The `ToValue` trait can be used to capture values generically.
60/// It's the bound used by `Source`.
61///
62/// ```
63/// # use log::kv::ToValue;
64/// let value = 42i32.to_value();
65///
66/// assert_eq!(Some(42), value.to_i64());
67/// ```
68///
69/// ## Using the standard `From` trait
70///
71/// Standard types that implement `ToValue` also implement `From`.
72///
73/// ```
74/// use log::kv::Value;
75///
76/// let value = Value::from(42i32);
77///
78/// assert_eq!(Some(42), value.to_i64());
79/// ```
80///
81/// # Data model
82///
83/// Values can hold one of a number of types:
84///
85/// - **Null:** The absence of any other meaningful value. Note that
86///   `Some(Value::null())` is not the same as `None`. The former is
87///   `null` while the latter is `undefined`. This is important to be
88///   able to tell the difference between a key-value that was logged,
89///   but its value was empty (`Some(Value::null())`) and a key-value
90///   that was never logged at all (`None`).
91/// - **Strings:** `str`, `char`.
92/// - **Booleans:** `bool`.
93/// - **Integers:** `u8`-`u128`, `i8`-`i128`, `NonZero*`.
94/// - **Floating point numbers:** `f32`-`f64`.
95/// - **Errors:** `dyn (Error + 'static)`.
96/// - **`serde`:** Any type in `serde`'s data model.
97/// - **`sval`:** Any type in `sval`'s data model.
98///
99/// # Serialization
100///
101/// Values provide a number of ways to be serialized.
102///
103/// For basic types the [`Value::visit`] method can be used to extract the
104/// underlying typed value. However, this is limited in the amount of types
105/// supported (see the [`VisitValue`] trait methods).
106///
107/// For more complex types one of the following traits can be used:
108///  * `sval::Value`, requires the `kv_sval` feature.
109///  * `serde::Serialize`, requires the `kv_serde` feature.
110///
111/// You don't need a visitor to serialize values through `serde` or `sval`.
112///
113/// A value can always be serialized using any supported framework, regardless
114/// of how it was captured. If, for example, a value was captured using its
115/// `Display` implementation, it will serialize through `serde` as a string. If it was
116/// captured as a struct using `serde`, it will also serialize as a struct
117/// through `sval`, or can be formatted using a `Debug`-compatible representation.
118#[derive(Clone)]
119pub struct Value<'v> {
120    inner: inner::Inner<'v>,
121}
122
123impl<'v> Value<'v> {
124    /// Get a value from a type implementing `ToValue`.
125    pub fn from_any<T>(value: &'v T) -> Self
126    where
127        T: ToValue,
128    {
129        value.to_value()
130    }
131
132    /// Get a value from a type implementing `std::fmt::Debug`.
133    pub fn from_debug<T>(value: &'v T) -> Self
134    where
135        T: fmt::Debug,
136    {
137        Value {
138            inner: inner::Inner::from_debug(value),
139        }
140    }
141
142    /// Get a value from a type implementing `std::fmt::Display`.
143    pub fn from_display<T>(value: &'v T) -> Self
144    where
145        T: fmt::Display,
146    {
147        Value {
148            inner: inner::Inner::from_display(value),
149        }
150    }
151
152    /// Get a value from a type implementing `serde::Serialize`.
153    #[cfg(feature = "kv_serde")]
154    pub fn from_serde<T>(value: &'v T) -> Self
155    where
156        T: serde_core::Serialize,
157    {
158        Value {
159            inner: inner::Inner::from_serde1(value),
160        }
161    }
162
163    /// Get a value from a type implementing `sval::Value`.
164    #[cfg(feature = "kv_sval")]
165    pub fn from_sval<T>(value: &'v T) -> Self
166    where
167        T: sval::Value,
168    {
169        Value {
170            inner: inner::Inner::from_sval2(value),
171        }
172    }
173
174    /// Get a value from a dynamic `std::fmt::Debug`.
175    pub fn from_dyn_debug(value: &'v dyn fmt::Debug) -> Self {
176        Value {
177            inner: inner::Inner::from_dyn_debug(value),
178        }
179    }
180
181    /// Get a value from a dynamic `std::fmt::Display`.
182    pub fn from_dyn_display(value: &'v dyn fmt::Display) -> Self {
183        Value {
184            inner: inner::Inner::from_dyn_display(value),
185        }
186    }
187
188    /// Get a value from a dynamic error.
189    #[cfg(feature = "kv_std")]
190    pub fn from_dyn_error(err: &'v (dyn std::error::Error + 'static)) -> Self {
191        Value {
192            inner: inner::Inner::from_dyn_error(err),
193        }
194    }
195
196    /// Get a `null` value.
197    pub fn null() -> Self {
198        Value {
199            inner: inner::Inner::empty(),
200        }
201    }
202
203    /// Get a value from an internal primitive.
204    fn from_inner<T>(value: T) -> Self
205    where
206        T: Into<inner::Inner<'v>>,
207    {
208        Value {
209            inner: value.into(),
210        }
211    }
212
213    /// Inspect this value using a simple visitor.
214    ///
215    /// When the `kv_serde` or `kv_sval` features are enabled, you can also
216    /// serialize a value using its `Serialize` or `Value` implementation.
217    pub fn visit(&self, visitor: impl VisitValue<'v>) -> Result<(), Error> {
218        inner::visit(&self.inner, visitor)
219    }
220}
221
222impl<'v> fmt::Debug for Value<'v> {
223    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
224        fmt::Debug::fmt(&self.inner, f)
225    }
226}
227
228impl<'v> fmt::Display for Value<'v> {
229    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
230        fmt::Display::fmt(&self.inner, f)
231    }
232}
233
234#[cfg(feature = "kv_serde")]
235impl<'v> serde_core::Serialize for Value<'v> {
236    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
237    where
238        S: serde_core::Serializer,
239    {
240        self.inner.serialize(s)
241    }
242}
243
244#[cfg(feature = "kv_sval")]
245impl<'v> sval::Value for Value<'v> {
246    fn stream<'sval, S: sval::Stream<'sval> + ?Sized>(&'sval self, stream: &mut S) -> sval::Result {
247        sval::Value::stream(&self.inner, stream)
248    }
249}
250
251#[cfg(feature = "kv_sval")]
252impl<'v> sval_ref::ValueRef<'v> for Value<'v> {
253    fn stream_ref<S: sval::Stream<'v> + ?Sized>(&self, stream: &mut S) -> sval::Result {
254        sval_ref::ValueRef::stream_ref(&self.inner, stream)
255    }
256}
257
258impl ToValue for str {
259    fn to_value(&self) -> Value<'_> {
260        Value::from(self)
261    }
262}
263
264impl<'v> From<&'v str> for Value<'v> {
265    fn from(value: &'v str) -> Self {
266        Value::from_inner(value)
267    }
268}
269
270impl ToValue for () {
271    fn to_value(&self) -> Value<'_> {
272        Value::from_inner(())
273    }
274}
275
276impl<T> ToValue for Option<T>
277where
278    T: ToValue,
279{
280    fn to_value(&self) -> Value<'_> {
281        match *self {
282            Some(ref value) => value.to_value(),
283            None => Value::from_inner(()),
284        }
285    }
286}
287
288macro_rules! impl_to_value_primitive {
289    ($($into_ty:ty,)*) => {
290        $(
291            impl ToValue for $into_ty {
292                fn to_value(&self) -> Value<'_> {
293                    Value::from(*self)
294                }
295            }
296
297            impl<'v> From<$into_ty> for Value<'v> {
298                fn from(value: $into_ty) -> Self {
299                    Value::from_inner(value)
300                }
301            }
302
303            impl<'v> From<&'v $into_ty> for Value<'v> {
304                fn from(value: &'v $into_ty) -> Self {
305                    Value::from_inner(*value)
306                }
307            }
308        )*
309    };
310}
311
312macro_rules! impl_to_value_nonzero_primitive {
313    ($($into_ty:ident,)*) => {
314        $(
315            impl ToValue for std::num::$into_ty {
316                fn to_value(&self) -> Value<'_> {
317                    Value::from(self.get())
318                }
319            }
320
321            impl<'v> From<std::num::$into_ty> for Value<'v> {
322                fn from(value: std::num::$into_ty) -> Self {
323                    Value::from(value.get())
324                }
325            }
326
327            impl<'v> From<&'v std::num::$into_ty> for Value<'v> {
328                fn from(value: &'v std::num::$into_ty) -> Self {
329                    Value::from(value.get())
330                }
331            }
332        )*
333    };
334}
335
336macro_rules! impl_value_to_primitive {
337    ($(#[doc = $doc:tt] $into_name:ident -> $into_ty:ty,)*) => {
338        impl<'v> Value<'v> {
339            $(
340                #[doc = $doc]
341                pub fn $into_name(&self) -> Option<$into_ty> {
342                    self.inner.$into_name()
343                }
344            )*
345        }
346    }
347}
348
349impl_to_value_primitive![
350    usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64, char, bool,
351];
352
353#[rustfmt::skip]
354impl_to_value_nonzero_primitive![
355    NonZeroUsize, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128,
356    NonZeroIsize, NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128,
357];
358
359impl_value_to_primitive![
360    #[doc = "Try convert this value into a `u64`."]
361    to_u64 -> u64,
362    #[doc = "Try convert this value into a `i64`."]
363    to_i64 -> i64,
364    #[doc = "Try convert this value into a `u128`."]
365    to_u128 -> u128,
366    #[doc = "Try convert this value into a `i128`."]
367    to_i128 -> i128,
368    #[doc = "Try convert this value into a `f64`."]
369    to_f64 -> f64,
370    #[doc = "Try convert this value into a `char`."]
371    to_char -> char,
372    #[doc = "Try convert this value into a `bool`."]
373    to_bool -> bool,
374];
375
376#[cfg(feature = "std")]
377macro_rules! impl_to_value_from_display {
378    ($($into_ty:ty,)*) => {
379        $(
380            impl ToValue for $into_ty {
381                fn to_value(&self) -> Value<'_> {
382                    Value::from_display(self)
383                }
384            }
385
386            impl<'v> From<&'v $into_ty> for Value<'v> {
387                fn from(value: &'v $into_ty) -> Self {
388                    Value::from_display(value)
389                }
390            }
391        )*
392    };
393}
394
395#[cfg(feature = "std")]
396impl_to_value_from_display![
397    std::net::IpAddr,
398    std::net::Ipv4Addr,
399    std::net::Ipv6Addr,
400    std::net::SocketAddr,
401    std::net::SocketAddrV4,
402    std::net::SocketAddrV6,
403];
404
405impl<'v> Value<'v> {
406    /// Try to convert this value into an error.
407    #[cfg(feature = "kv_std")]
408    pub fn to_borrowed_error(&self) -> Option<&(dyn std::error::Error + 'static)> {
409        self.inner.to_borrowed_error()
410    }
411
412    /// Try to convert this value into a borrowed string.
413    pub fn to_borrowed_str(&self) -> Option<&'v str> {
414        self.inner.to_borrowed_str()
415    }
416}
417
418#[cfg(feature = "std")]
419mod std_support {
420    use std::borrow::Cow;
421    use std::rc::Rc;
422    use std::sync::Arc;
423
424    use super::*;
425
426    impl<T> ToValue for Box<T>
427    where
428        T: ToValue + ?Sized,
429    {
430        fn to_value(&self) -> Value<'_> {
431            (**self).to_value()
432        }
433    }
434
435    impl<T> ToValue for Arc<T>
436    where
437        T: ToValue + ?Sized,
438    {
439        fn to_value(&self) -> Value<'_> {
440            (**self).to_value()
441        }
442    }
443
444    impl<T> ToValue for Rc<T>
445    where
446        T: ToValue + ?Sized,
447    {
448        fn to_value(&self) -> Value<'_> {
449            (**self).to_value()
450        }
451    }
452
453    impl ToValue for String {
454        fn to_value(&self) -> Value<'_> {
455            Value::from(&**self)
456        }
457    }
458
459    impl<'v> ToValue for Cow<'v, str> {
460        fn to_value(&self) -> Value<'_> {
461            Value::from(&**self)
462        }
463    }
464
465    #[cfg(feature = "kv_std")]
466    impl<'v> Value<'v> {
467        /// Try convert this value into a string.
468        pub fn to_cow_str(&self) -> Option<Cow<'v, str>> {
469            self.inner.to_str()
470        }
471    }
472
473    impl<'v> From<&'v String> for Value<'v> {
474        fn from(v: &'v String) -> Self {
475            Value::from(&**v)
476        }
477    }
478}
479
480/// A visitor for a [`Value`].
481///
482/// Also see [`Value`'s documentation on serialization]. Value visitors are a simple alternative
483/// to a more fully-featured serialization framework like `serde` or `sval`. A value visitor
484/// can differentiate primitive types through methods like [`VisitValue::visit_bool`] and
485/// [`VisitValue::visit_str`], but more complex types like maps and sequences
486/// will fallthrough to [`VisitValue::visit_any`].
487///
488/// If you're trying to serialize a value to a format like JSON, you can use either `serde`
489/// or `sval` directly with the value. You don't need a visitor.
490///
491/// [`Value`'s documentation on serialization]: Value#serialization
492pub trait VisitValue<'v> {
493    /// Visit a `Value`.
494    ///
495    /// This is the only required method on `VisitValue` and acts as a fallback for any
496    /// more specific methods that aren't overridden.
497    /// The `Value` may be formatted using its `fmt::Debug` or `fmt::Display` implementation,
498    /// or serialized using its `sval::Value` or `serde::Serialize` implementation.
499    fn visit_any(&mut self, value: Value) -> Result<(), Error>;
500
501    /// Visit an empty value.
502    fn visit_null(&mut self) -> Result<(), Error> {
503        self.visit_any(Value::null())
504    }
505
506    /// Visit an unsigned integer.
507    fn visit_u64(&mut self, value: u64) -> Result<(), Error> {
508        self.visit_any(value.into())
509    }
510
511    /// Visit a signed integer.
512    fn visit_i64(&mut self, value: i64) -> Result<(), Error> {
513        self.visit_any(value.into())
514    }
515
516    /// Visit a big unsigned integer.
517    fn visit_u128(&mut self, value: u128) -> Result<(), Error> {
518        self.visit_any((value).into())
519    }
520
521    /// Visit a big signed integer.
522    fn visit_i128(&mut self, value: i128) -> Result<(), Error> {
523        self.visit_any((value).into())
524    }
525
526    /// Visit a floating point.
527    fn visit_f64(&mut self, value: f64) -> Result<(), Error> {
528        self.visit_any(value.into())
529    }
530
531    /// Visit a boolean.
532    fn visit_bool(&mut self, value: bool) -> Result<(), Error> {
533        self.visit_any(value.into())
534    }
535
536    /// Visit a string.
537    fn visit_str(&mut self, value: &str) -> Result<(), Error> {
538        self.visit_any(value.into())
539    }
540
541    /// Visit a string.
542    fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), Error> {
543        self.visit_str(value)
544    }
545
546    /// Visit a Unicode character.
547    fn visit_char(&mut self, value: char) -> Result<(), Error> {
548        let mut b = [0; 4];
549        self.visit_str(&*value.encode_utf8(&mut b))
550    }
551
552    /// Visit an error.
553    #[cfg(feature = "kv_std")]
554    fn visit_error(&mut self, err: &(dyn std::error::Error + 'static)) -> Result<(), Error> {
555        self.visit_any(Value::from_dyn_error(err))
556    }
557
558    /// Visit an error.
559    #[cfg(feature = "kv_std")]
560    fn visit_borrowed_error(
561        &mut self,
562        err: &'v (dyn std::error::Error + 'static),
563    ) -> Result<(), Error> {
564        self.visit_any(Value::from_dyn_error(err))
565    }
566}
567
568#[allow(clippy::needless_lifetimes)] // Not needless.
569impl<'a, 'v, T: ?Sized> VisitValue<'v> for &'a mut T
570where
571    T: VisitValue<'v>,
572{
573    fn visit_any(&mut self, value: Value) -> Result<(), Error> {
574        (**self).visit_any(value)
575    }
576
577    fn visit_null(&mut self) -> Result<(), Error> {
578        (**self).visit_null()
579    }
580
581    fn visit_u64(&mut self, value: u64) -> Result<(), Error> {
582        (**self).visit_u64(value)
583    }
584
585    fn visit_i64(&mut self, value: i64) -> Result<(), Error> {
586        (**self).visit_i64(value)
587    }
588
589    fn visit_u128(&mut self, value: u128) -> Result<(), Error> {
590        (**self).visit_u128(value)
591    }
592
593    fn visit_i128(&mut self, value: i128) -> Result<(), Error> {
594        (**self).visit_i128(value)
595    }
596
597    fn visit_f64(&mut self, value: f64) -> Result<(), Error> {
598        (**self).visit_f64(value)
599    }
600
601    fn visit_bool(&mut self, value: bool) -> Result<(), Error> {
602        (**self).visit_bool(value)
603    }
604
605    fn visit_str(&mut self, value: &str) -> Result<(), Error> {
606        (**self).visit_str(value)
607    }
608
609    fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), Error> {
610        (**self).visit_borrowed_str(value)
611    }
612
613    fn visit_char(&mut self, value: char) -> Result<(), Error> {
614        (**self).visit_char(value)
615    }
616
617    #[cfg(feature = "kv_std")]
618    fn visit_error(&mut self, err: &(dyn std::error::Error + 'static)) -> Result<(), Error> {
619        (**self).visit_error(err)
620    }
621
622    #[cfg(feature = "kv_std")]
623    fn visit_borrowed_error(
624        &mut self,
625        err: &'v (dyn std::error::Error + 'static),
626    ) -> Result<(), Error> {
627        (**self).visit_borrowed_error(err)
628    }
629}
630
631#[cfg(feature = "value-bag")]
632pub(in crate::kv) mod inner {
633    /**
634    An implementation of `Value` based on a library called `value_bag`.
635
636    `value_bag` was written specifically for use in `log`'s value, but was split out when it outgrew
637    the codebase here. It's a general-purpose type-erasure library that handles mapping between
638    more fully-featured serialization frameworks.
639    */
640    use super::*;
641
642    pub use value_bag::ValueBag as Inner;
643
644    pub use value_bag::Error;
645
646    #[cfg(test)]
647    pub use value_bag::test::TestToken as Token;
648
649    pub fn visit<'v>(
650        inner: &Inner<'v>,
651        visitor: impl VisitValue<'v>,
652    ) -> Result<(), crate::kv::Error> {
653        struct InnerVisitValue<V>(V);
654
655        impl<'v, V> value_bag::visit::Visit<'v> for InnerVisitValue<V>
656        where
657            V: VisitValue<'v>,
658        {
659            fn visit_any(&mut self, value: value_bag::ValueBag) -> Result<(), Error> {
660                self.0
661                    .visit_any(Value { inner: value })
662                    .map_err(crate::kv::Error::into_value)
663            }
664
665            fn visit_empty(&mut self) -> Result<(), Error> {
666                self.0.visit_null().map_err(crate::kv::Error::into_value)
667            }
668
669            fn visit_u64(&mut self, value: u64) -> Result<(), Error> {
670                self.0
671                    .visit_u64(value)
672                    .map_err(crate::kv::Error::into_value)
673            }
674
675            fn visit_i64(&mut self, value: i64) -> Result<(), Error> {
676                self.0
677                    .visit_i64(value)
678                    .map_err(crate::kv::Error::into_value)
679            }
680
681            fn visit_u128(&mut self, value: u128) -> Result<(), Error> {
682                self.0
683                    .visit_u128(value)
684                    .map_err(crate::kv::Error::into_value)
685            }
686
687            fn visit_i128(&mut self, value: i128) -> Result<(), Error> {
688                self.0
689                    .visit_i128(value)
690                    .map_err(crate::kv::Error::into_value)
691            }
692
693            fn visit_f64(&mut self, value: f64) -> Result<(), Error> {
694                self.0
695                    .visit_f64(value)
696                    .map_err(crate::kv::Error::into_value)
697            }
698
699            fn visit_bool(&mut self, value: bool) -> Result<(), Error> {
700                self.0
701                    .visit_bool(value)
702                    .map_err(crate::kv::Error::into_value)
703            }
704
705            fn visit_str(&mut self, value: &str) -> Result<(), Error> {
706                self.0
707                    .visit_str(value)
708                    .map_err(crate::kv::Error::into_value)
709            }
710
711            fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), Error> {
712                self.0
713                    .visit_borrowed_str(value)
714                    .map_err(crate::kv::Error::into_value)
715            }
716
717            fn visit_char(&mut self, value: char) -> Result<(), Error> {
718                self.0
719                    .visit_char(value)
720                    .map_err(crate::kv::Error::into_value)
721            }
722
723            #[cfg(feature = "kv_std")]
724            fn visit_error(
725                &mut self,
726                err: &(dyn std::error::Error + 'static),
727            ) -> Result<(), Error> {
728                self.0
729                    .visit_error(err)
730                    .map_err(crate::kv::Error::into_value)
731            }
732
733            #[cfg(feature = "kv_std")]
734            fn visit_borrowed_error(
735                &mut self,
736                err: &'v (dyn std::error::Error + 'static),
737            ) -> Result<(), Error> {
738                self.0
739                    .visit_borrowed_error(err)
740                    .map_err(crate::kv::Error::into_value)
741            }
742        }
743
744        inner
745            .visit(&mut InnerVisitValue(visitor))
746            .map_err(crate::kv::Error::from_value)
747    }
748}
749
750#[cfg(not(feature = "value-bag"))]
751pub(in crate::kv) mod inner {
752    /**
753    This is a dependency-free implementation of `Value` when there's no serialization frameworks involved.
754    In these simple cases a more fully featured solution like `value_bag` isn't needed, so we avoid pulling it in.
755
756    There are a few things here that need to remain consistent with the `value_bag`-based implementation:
757
758    1. Conversions should always produce the same results. If a conversion here returns `Some`, then
759       the same `value_bag`-based conversion must also. Of particular note here are floats to ints; they're
760       based on the standard library's `TryInto` conversions, which need to be converted to `i32` or `u32`,
761       and then to `f64`.
762    2. VisitValues should always be called in the same way. If a particular type of value calls `visit_i64`,
763       then the same `value_bag`-based visitor must also.
764    */
765    use super::*;
766
767    #[derive(Clone)]
768    pub enum Inner<'v> {
769        // NOTE: New variants can't be added here; see the module-level doc above
770        None,
771        Bool(bool),
772        Str(&'v str),
773        Char(char),
774        I64(i64),
775        U64(u64),
776        F64(f64),
777        I128(i128),
778        U128(u128),
779        Debug(&'v dyn fmt::Debug),
780        Display(&'v dyn fmt::Display),
781    }
782
783    impl<'v> From<()> for Inner<'v> {
784        fn from(_: ()) -> Self {
785            Inner::None
786        }
787    }
788
789    impl<'v> From<bool> for Inner<'v> {
790        fn from(v: bool) -> Self {
791            Inner::Bool(v)
792        }
793    }
794
795    impl<'v> From<char> for Inner<'v> {
796        fn from(v: char) -> Self {
797            Inner::Char(v)
798        }
799    }
800
801    impl<'v> From<f32> for Inner<'v> {
802        fn from(v: f32) -> Self {
803            Inner::F64(v as f64)
804        }
805    }
806
807    impl<'v> From<f64> for Inner<'v> {
808        fn from(v: f64) -> Self {
809            Inner::F64(v)
810        }
811    }
812
813    impl<'v> From<i8> for Inner<'v> {
814        fn from(v: i8) -> Self {
815            Inner::I64(v as i64)
816        }
817    }
818
819    impl<'v> From<i16> for Inner<'v> {
820        fn from(v: i16) -> Self {
821            Inner::I64(v as i64)
822        }
823    }
824
825    impl<'v> From<i32> for Inner<'v> {
826        fn from(v: i32) -> Self {
827            Inner::I64(v as i64)
828        }
829    }
830
831    impl<'v> From<i64> for Inner<'v> {
832        fn from(v: i64) -> Self {
833            Inner::I64(v as i64)
834        }
835    }
836
837    impl<'v> From<isize> for Inner<'v> {
838        fn from(v: isize) -> Self {
839            Inner::I64(v as i64)
840        }
841    }
842
843    impl<'v> From<u8> for Inner<'v> {
844        fn from(v: u8) -> Self {
845            Inner::U64(v as u64)
846        }
847    }
848
849    impl<'v> From<u16> for Inner<'v> {
850        fn from(v: u16) -> Self {
851            Inner::U64(v as u64)
852        }
853    }
854
855    impl<'v> From<u32> for Inner<'v> {
856        fn from(v: u32) -> Self {
857            Inner::U64(v as u64)
858        }
859    }
860
861    impl<'v> From<u64> for Inner<'v> {
862        fn from(v: u64) -> Self {
863            Inner::U64(v as u64)
864        }
865    }
866
867    impl<'v> From<usize> for Inner<'v> {
868        fn from(v: usize) -> Self {
869            Inner::U64(v as u64)
870        }
871    }
872
873    impl<'v> From<i128> for Inner<'v> {
874        fn from(v: i128) -> Self {
875            Inner::I128(v)
876        }
877    }
878
879    impl<'v> From<u128> for Inner<'v> {
880        fn from(v: u128) -> Self {
881            Inner::U128(v)
882        }
883    }
884
885    impl<'v> From<&'v str> for Inner<'v> {
886        fn from(v: &'v str) -> Self {
887            Inner::Str(v)
888        }
889    }
890
891    impl<'v> fmt::Debug for Inner<'v> {
892        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
893            match self {
894                Inner::None => fmt::Debug::fmt(&None::<()>, f),
895                Inner::Bool(v) => fmt::Debug::fmt(v, f),
896                Inner::Str(v) => fmt::Debug::fmt(v, f),
897                Inner::Char(v) => fmt::Debug::fmt(v, f),
898                Inner::I64(v) => fmt::Debug::fmt(v, f),
899                Inner::U64(v) => fmt::Debug::fmt(v, f),
900                Inner::F64(v) => fmt::Debug::fmt(v, f),
901                Inner::I128(v) => fmt::Debug::fmt(v, f),
902                Inner::U128(v) => fmt::Debug::fmt(v, f),
903                Inner::Debug(v) => fmt::Debug::fmt(v, f),
904                Inner::Display(v) => fmt::Display::fmt(v, f),
905            }
906        }
907    }
908
909    impl<'v> fmt::Display for Inner<'v> {
910        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
911            match self {
912                Inner::None => fmt::Debug::fmt(&None::<()>, f),
913                Inner::Bool(v) => fmt::Display::fmt(v, f),
914                Inner::Str(v) => fmt::Display::fmt(v, f),
915                Inner::Char(v) => fmt::Display::fmt(v, f),
916                Inner::I64(v) => fmt::Display::fmt(v, f),
917                Inner::U64(v) => fmt::Display::fmt(v, f),
918                Inner::F64(v) => fmt::Display::fmt(v, f),
919                Inner::I128(v) => fmt::Display::fmt(v, f),
920                Inner::U128(v) => fmt::Display::fmt(v, f),
921                Inner::Debug(v) => fmt::Debug::fmt(v, f),
922                Inner::Display(v) => fmt::Display::fmt(v, f),
923            }
924        }
925    }
926
927    impl<'v> Inner<'v> {
928        pub fn from_debug<T: fmt::Debug>(value: &'v T) -> Self {
929            Inner::Debug(value)
930        }
931
932        pub fn from_display<T: fmt::Display>(value: &'v T) -> Self {
933            Inner::Display(value)
934        }
935
936        pub fn from_dyn_debug(value: &'v dyn fmt::Debug) -> Self {
937            Inner::Debug(value)
938        }
939
940        pub fn from_dyn_display(value: &'v dyn fmt::Display) -> Self {
941            Inner::Display(value)
942        }
943
944        pub fn empty() -> Self {
945            Inner::None
946        }
947
948        pub fn to_bool(&self) -> Option<bool> {
949            match self {
950                Inner::Bool(v) => Some(*v),
951                _ => None,
952            }
953        }
954
955        pub fn to_char(&self) -> Option<char> {
956            match self {
957                Inner::Char(v) => Some(*v),
958                _ => None,
959            }
960        }
961
962        pub fn to_f64(&self) -> Option<f64> {
963            match self {
964                Inner::F64(v) => Some(*v),
965                Inner::I64(v) => {
966                    let v: i32 = (*v).try_into().ok()?;
967                    v.try_into().ok()
968                }
969                Inner::U64(v) => {
970                    let v: u32 = (*v).try_into().ok()?;
971                    v.try_into().ok()
972                }
973                Inner::I128(v) => {
974                    let v: i32 = (*v).try_into().ok()?;
975                    v.try_into().ok()
976                }
977                Inner::U128(v) => {
978                    let v: u32 = (*v).try_into().ok()?;
979                    v.try_into().ok()
980                }
981                _ => None,
982            }
983        }
984
985        pub fn to_i64(&self) -> Option<i64> {
986            match self {
987                Inner::I64(v) => Some(*v),
988                Inner::U64(v) => (*v).try_into().ok(),
989                Inner::I128(v) => (*v).try_into().ok(),
990                Inner::U128(v) => (*v).try_into().ok(),
991                _ => None,
992            }
993        }
994
995        pub fn to_u64(&self) -> Option<u64> {
996            match self {
997                Inner::U64(v) => Some(*v),
998                Inner::I64(v) => (*v).try_into().ok(),
999                Inner::I128(v) => (*v).try_into().ok(),
1000                Inner::U128(v) => (*v).try_into().ok(),
1001                _ => None,
1002            }
1003        }
1004
1005        pub fn to_u128(&self) -> Option<u128> {
1006            match self {
1007                Inner::U128(v) => Some(*v),
1008                Inner::I64(v) => (*v).try_into().ok(),
1009                Inner::U64(v) => (*v).try_into().ok(),
1010                Inner::I128(v) => (*v).try_into().ok(),
1011                _ => None,
1012            }
1013        }
1014
1015        pub fn to_i128(&self) -> Option<i128> {
1016            match self {
1017                Inner::I128(v) => Some(*v),
1018                Inner::I64(v) => (*v).try_into().ok(),
1019                Inner::U64(v) => (*v).try_into().ok(),
1020                Inner::U128(v) => (*v).try_into().ok(),
1021                _ => None,
1022            }
1023        }
1024
1025        pub fn to_borrowed_str(&self) -> Option<&'v str> {
1026            match self {
1027                Inner::Str(v) => Some(v),
1028                _ => None,
1029            }
1030        }
1031
1032        #[cfg(test)]
1033        pub fn to_test_token(&self) -> Token<'_> {
1034            match self {
1035                Inner::None => Token::None,
1036                Inner::Bool(v) => Token::Bool(*v),
1037                Inner::Str(v) => Token::Str(*v),
1038                Inner::Char(v) => Token::Char(*v),
1039                Inner::I64(v) => Token::I64(*v),
1040                Inner::U64(v) => Token::U64(*v),
1041                Inner::F64(v) => Token::F64(*v),
1042                Inner::I128(_) => unimplemented!(),
1043                Inner::U128(_) => unimplemented!(),
1044                Inner::Debug(_) => unimplemented!(),
1045                Inner::Display(_) => unimplemented!(),
1046            }
1047        }
1048    }
1049
1050    #[cfg(test)]
1051    #[derive(Debug, PartialEq)]
1052    pub enum Token<'v> {
1053        None,
1054        Bool(bool),
1055        Char(char),
1056        Str(&'v str),
1057        F64(f64),
1058        I64(i64),
1059        U64(u64),
1060    }
1061
1062    pub fn visit<'v>(
1063        inner: &Inner<'v>,
1064        mut visitor: impl VisitValue<'v>,
1065    ) -> Result<(), crate::kv::Error> {
1066        match inner {
1067            Inner::None => visitor.visit_null(),
1068            Inner::Bool(v) => visitor.visit_bool(*v),
1069            Inner::Str(v) => visitor.visit_borrowed_str(*v),
1070            Inner::Char(v) => visitor.visit_char(*v),
1071            Inner::I64(v) => visitor.visit_i64(*v),
1072            Inner::U64(v) => visitor.visit_u64(*v),
1073            Inner::F64(v) => visitor.visit_f64(*v),
1074            Inner::I128(v) => visitor.visit_i128(*v),
1075            Inner::U128(v) => visitor.visit_u128(*v),
1076            Inner::Debug(v) => visitor.visit_any(Value::from_dyn_debug(*v)),
1077            Inner::Display(v) => visitor.visit_any(Value::from_dyn_display(*v)),
1078        }
1079    }
1080}
1081
1082impl<'v> Value<'v> {
1083    /// Get a value from a type implementing `std::fmt::Debug`.
1084    #[cfg(feature = "kv_unstable")]
1085    #[deprecated(note = "use `from_debug` instead")]
1086    pub fn capture_debug<T>(value: &'v T) -> Self
1087    where
1088        T: fmt::Debug + 'static,
1089    {
1090        Value::from_debug(value)
1091    }
1092
1093    /// Get a value from a type implementing `std::fmt::Display`.
1094    #[cfg(feature = "kv_unstable")]
1095    #[deprecated(note = "use `from_display` instead")]
1096    pub fn capture_display<T>(value: &'v T) -> Self
1097    where
1098        T: fmt::Display + 'static,
1099    {
1100        Value::from_display(value)
1101    }
1102
1103    /// Get a value from an error.
1104    #[cfg(feature = "kv_unstable_std")]
1105    #[deprecated(note = "use `from_dyn_error` instead")]
1106    pub fn capture_error<T>(err: &'v T) -> Self
1107    where
1108        T: std::error::Error + 'static,
1109    {
1110        Value::from_dyn_error(err)
1111    }
1112
1113    /// Get a value from a type implementing `serde::Serialize`.
1114    #[cfg(feature = "kv_unstable_serde")]
1115    #[deprecated(note = "use `from_serde` instead")]
1116    pub fn capture_serde<T>(value: &'v T) -> Self
1117    where
1118        T: serde_core::Serialize + 'static,
1119    {
1120        Value::from_serde(value)
1121    }
1122
1123    /// Get a value from a type implementing `sval::Value`.
1124    #[cfg(feature = "kv_unstable_sval")]
1125    #[deprecated(note = "use `from_sval` instead")]
1126    pub fn capture_sval<T>(value: &'v T) -> Self
1127    where
1128        T: sval::Value + 'static,
1129    {
1130        Value::from_sval(value)
1131    }
1132
1133    /// Check whether this value can be downcast to `T`.
1134    #[cfg(feature = "kv_unstable")]
1135    #[deprecated(
1136        note = "downcasting has been removed; log an issue at https://github.com/rust-lang/log/issues if this is something you rely on"
1137    )]
1138    pub fn is<T: 'static>(&self) -> bool {
1139        false
1140    }
1141
1142    /// Try downcast this value to `T`.
1143    #[cfg(feature = "kv_unstable")]
1144    #[deprecated(
1145        note = "downcasting has been removed; log an issue at https://github.com/rust-lang/log/issues if this is something you rely on"
1146    )]
1147    pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
1148        None
1149    }
1150}
1151
1152// NOTE: Deprecated; but aliases can't carry this attribute
1153#[cfg(feature = "kv_unstable")]
1154pub use VisitValue as Visit;
1155
1156/// Get a value from a type implementing `std::fmt::Debug`.
1157#[cfg(feature = "kv_unstable")]
1158#[deprecated(note = "use the `key:? = value` macro syntax instead")]
1159#[macro_export]
1160macro_rules! as_debug {
1161    ($capture:expr) => {
1162        $crate::kv::Value::from_debug(&$capture)
1163    };
1164}
1165
1166/// Get a value from a type implementing `std::fmt::Display`.
1167#[cfg(feature = "kv_unstable")]
1168#[deprecated(note = "use the `key:% = value` macro syntax instead")]
1169#[macro_export]
1170macro_rules! as_display {
1171    ($capture:expr) => {
1172        $crate::kv::Value::from_display(&$capture)
1173    };
1174}
1175
1176/// Get a value from an error.
1177#[cfg(feature = "kv_unstable_std")]
1178#[deprecated(note = "use the `key:err = value` macro syntax instead")]
1179#[macro_export]
1180macro_rules! as_error {
1181    ($capture:expr) => {
1182        $crate::kv::Value::from_dyn_error(&$capture)
1183    };
1184}
1185
1186#[cfg(feature = "kv_unstable_serde")]
1187#[deprecated(note = "use the `key:serde = value` macro syntax instead")]
1188/// Get a value from a type implementing `serde::Serialize`.
1189#[macro_export]
1190macro_rules! as_serde {
1191    ($capture:expr) => {
1192        $crate::kv::Value::from_serde(&$capture)
1193    };
1194}
1195
1196/// Get a value from a type implementing `sval::Value`.
1197#[cfg(feature = "kv_unstable_sval")]
1198#[deprecated(note = "use the `key:sval = value` macro syntax instead")]
1199#[macro_export]
1200macro_rules! as_sval {
1201    ($capture:expr) => {
1202        $crate::kv::Value::from_sval(&$capture)
1203    };
1204}
1205
1206#[cfg(test)]
1207pub(crate) mod tests {
1208    use super::*;
1209
1210    // For new `ToValue` implementations, also add a test to the `tests/macros` file
1211
1212    impl<'v> Value<'v> {
1213        #[allow(mismatched_lifetime_syntaxes)]
1214        pub(crate) fn to_token(&self) -> inner::Token {
1215            self.inner.to_test_token()
1216        }
1217    }
1218
1219    fn unsigned() -> impl Iterator<Item = Value<'static>> {
1220        vec![
1221            Value::from(8u8),
1222            Value::from(16u16),
1223            Value::from(32u32),
1224            Value::from(64u64),
1225            Value::from(1usize),
1226            Value::from(std::num::NonZeroU8::new(8).unwrap()),
1227            Value::from(std::num::NonZeroU16::new(16).unwrap()),
1228            Value::from(std::num::NonZeroU32::new(32).unwrap()),
1229            Value::from(std::num::NonZeroU64::new(64).unwrap()),
1230            Value::from(std::num::NonZeroUsize::new(1).unwrap()),
1231        ]
1232        .into_iter()
1233    }
1234
1235    fn signed() -> impl Iterator<Item = Value<'static>> {
1236        vec![
1237            Value::from(-8i8),
1238            Value::from(-16i16),
1239            Value::from(-32i32),
1240            Value::from(-64i64),
1241            Value::from(-1isize),
1242            Value::from(std::num::NonZeroI8::new(-8).unwrap()),
1243            Value::from(std::num::NonZeroI16::new(-16).unwrap()),
1244            Value::from(std::num::NonZeroI32::new(-32).unwrap()),
1245            Value::from(std::num::NonZeroI64::new(-64).unwrap()),
1246            Value::from(std::num::NonZeroIsize::new(-1).unwrap()),
1247        ]
1248        .into_iter()
1249    }
1250
1251    fn float() -> impl Iterator<Item = Value<'static>> {
1252        vec![Value::from(32.32f32), Value::from(64.64f64)].into_iter()
1253    }
1254
1255    fn bool() -> impl Iterator<Item = Value<'static>> {
1256        vec![Value::from(true), Value::from(false)].into_iter()
1257    }
1258
1259    fn str() -> impl Iterator<Item = Value<'static>> {
1260        vec![Value::from("a string"), Value::from("a loong string")].into_iter()
1261    }
1262
1263    fn char() -> impl Iterator<Item = Value<'static>> {
1264        vec![Value::from('a'), Value::from('⛰')].into_iter()
1265    }
1266
1267    #[test]
1268    fn test_to_value_display() {
1269        assert_eq!(42u64.to_value().to_string(), "42");
1270        assert_eq!(42i64.to_value().to_string(), "42");
1271        assert_eq!(42.01f64.to_value().to_string(), "42.01");
1272        assert_eq!(true.to_value().to_string(), "true");
1273        assert_eq!('a'.to_value().to_string(), "a");
1274        assert_eq!("a loong string".to_value().to_string(), "a loong string");
1275        assert_eq!(Some(true).to_value().to_string(), "true");
1276        assert_eq!(().to_value().to_string(), "None");
1277        assert_eq!(None::<bool>.to_value().to_string(), "None");
1278    }
1279
1280    #[test]
1281    #[cfg(feature = "std")]
1282    fn test_net_to_value_display() {
1283        use std::str::FromStr;
1284
1285        assert_eq!(
1286            std::net::Ipv4Addr::new(192, 168, 10, 100)
1287                .to_value()
1288                .to_string(),
1289            "192.168.10.100"
1290        );
1291        assert_eq!(
1292            std::net::Ipv6Addr::from_str("f33c::1")
1293                .unwrap()
1294                .to_value()
1295                .to_string(),
1296            "f33c::1"
1297        );
1298        assert_eq!(
1299            std::net::IpAddr::V4(std::net::Ipv4Addr::new(192, 168, 10, 100))
1300                .to_value()
1301                .to_string(),
1302            "192.168.10.100"
1303        );
1304        assert_eq!(
1305            std::net::IpAddr::V6(std::net::Ipv6Addr::from_str("f33c::1").unwrap())
1306                .to_value()
1307                .to_string(),
1308            "f33c::1"
1309        );
1310        assert_eq!(
1311            std::net::SocketAddrV4::new(std::net::Ipv4Addr::new(192, 168, 10, 100), 12345)
1312                .to_value()
1313                .to_string(),
1314            "192.168.10.100:12345"
1315        );
1316        assert_eq!(
1317            std::net::SocketAddrV6::new(
1318                std::net::Ipv6Addr::from_str("f33c::1").unwrap(),
1319                12345,
1320                0,
1321                0
1322            )
1323            .to_value()
1324            .to_string(),
1325            "[f33c::1]:12345"
1326        );
1327        assert_eq!(
1328            std::net::SocketAddr::V4(std::net::SocketAddrV4::new(
1329                std::net::Ipv4Addr::new(192, 168, 10, 100),
1330                12345
1331            ))
1332            .to_value()
1333            .to_string(),
1334            "192.168.10.100:12345"
1335        );
1336        assert_eq!(
1337            std::net::SocketAddr::V6(std::net::SocketAddrV6::new(
1338                std::net::Ipv6Addr::from_str("f33c::1").unwrap(),
1339                12345,
1340                0,
1341                0
1342            ))
1343            .to_value()
1344            .to_string(),
1345            "[f33c::1]:12345"
1346        );
1347    }
1348
1349    #[test]
1350    fn test_to_value_structured() {
1351        assert_eq!(42u64.to_value().to_token(), inner::Token::U64(42));
1352        assert_eq!(42i64.to_value().to_token(), inner::Token::I64(42));
1353        assert_eq!(42.01f64.to_value().to_token(), inner::Token::F64(42.01));
1354        assert_eq!(true.to_value().to_token(), inner::Token::Bool(true));
1355        assert_eq!('a'.to_value().to_token(), inner::Token::Char('a'));
1356        assert_eq!(
1357            "a loong string".to_value().to_token(),
1358            inner::Token::Str("a loong string".into())
1359        );
1360        assert_eq!(Some(true).to_value().to_token(), inner::Token::Bool(true));
1361        assert_eq!(().to_value().to_token(), inner::Token::None);
1362        assert_eq!(None::<bool>.to_value().to_token(), inner::Token::None);
1363    }
1364
1365    #[test]
1366    fn test_to_number() {
1367        for v in unsigned() {
1368            assert!(v.to_u64().is_some());
1369            assert!(v.to_i64().is_some());
1370        }
1371
1372        for v in signed() {
1373            assert!(v.to_i64().is_some());
1374        }
1375
1376        for v in unsigned().chain(signed()).chain(float()) {
1377            assert!(v.to_f64().is_some());
1378        }
1379
1380        for v in bool().chain(str()).chain(char()) {
1381            assert!(v.to_u64().is_none());
1382            assert!(v.to_i64().is_none());
1383            assert!(v.to_f64().is_none());
1384        }
1385    }
1386
1387    #[test]
1388    fn test_to_float() {
1389        // Only integers from i32::MIN..=u32::MAX can be converted into floats
1390        assert!(Value::from(i32::MIN).to_f64().is_some());
1391        assert!(Value::from(u32::MAX).to_f64().is_some());
1392
1393        assert!(Value::from((i32::MIN as i64) - 1).to_f64().is_none());
1394        assert!(Value::from((u32::MAX as u64) + 1).to_f64().is_none());
1395    }
1396
1397    #[test]
1398    fn test_to_cow_str() {
1399        for v in str() {
1400            assert!(v.to_borrowed_str().is_some());
1401
1402            #[cfg(feature = "kv_std")]
1403            assert!(v.to_cow_str().is_some());
1404        }
1405
1406        let short_lived = String::from("short lived");
1407        let v = Value::from(&*short_lived);
1408
1409        assert!(v.to_borrowed_str().is_some());
1410
1411        #[cfg(feature = "kv_std")]
1412        assert!(v.to_cow_str().is_some());
1413
1414        for v in unsigned().chain(signed()).chain(float()).chain(bool()) {
1415            assert!(v.to_borrowed_str().is_none());
1416
1417            #[cfg(feature = "kv_std")]
1418            assert!(v.to_cow_str().is_none());
1419        }
1420    }
1421
1422    #[test]
1423    fn test_to_bool() {
1424        for v in bool() {
1425            assert!(v.to_bool().is_some());
1426        }
1427
1428        for v in unsigned()
1429            .chain(signed())
1430            .chain(float())
1431            .chain(str())
1432            .chain(char())
1433        {
1434            assert!(v.to_bool().is_none());
1435        }
1436    }
1437
1438    #[test]
1439    fn test_to_char() {
1440        for v in char() {
1441            assert!(v.to_char().is_some());
1442        }
1443
1444        for v in unsigned()
1445            .chain(signed())
1446            .chain(float())
1447            .chain(str())
1448            .chain(bool())
1449        {
1450            assert!(v.to_char().is_none());
1451        }
1452    }
1453
1454    #[test]
1455    fn test_visit_integer() {
1456        struct Extract(Option<u64>);
1457
1458        impl<'v> VisitValue<'v> for Extract {
1459            fn visit_any(&mut self, value: Value) -> Result<(), Error> {
1460                unimplemented!("unexpected value: {value:?}")
1461            }
1462
1463            fn visit_u64(&mut self, value: u64) -> Result<(), Error> {
1464                self.0 = Some(value);
1465
1466                Ok(())
1467            }
1468        }
1469
1470        let mut extract = Extract(None);
1471        Value::from(42u64).visit(&mut extract).unwrap();
1472
1473        assert_eq!(Some(42), extract.0);
1474    }
1475
1476    #[test]
1477    fn test_visit_borrowed_str() {
1478        struct Extract<'v>(Option<&'v str>);
1479
1480        impl<'v> VisitValue<'v> for Extract<'v> {
1481            fn visit_any(&mut self, value: Value) -> Result<(), Error> {
1482                unimplemented!("unexpected value: {value:?}")
1483            }
1484
1485            fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), Error> {
1486                self.0 = Some(value);
1487
1488                Ok(())
1489            }
1490        }
1491
1492        let mut extract = Extract(None);
1493
1494        let short_lived = String::from("A short-lived string");
1495        Value::from(&*short_lived).visit(&mut extract).unwrap();
1496
1497        assert_eq!(Some("A short-lived string"), extract.0);
1498    }
1499}