Skip to main content

storm_config/
value.rs

1use crate::errors::{ConfigError, Result, Unexpected};
2use crate::map::Map;
3use serde::de::{Deserialize, Deserializer, Visitor};
4use std::fmt;
5use std::fmt::Display;
6
7/// Underlying kind of the configuration value.
8///
9/// Standard operations on a `Value` by users of this crate do not require
10/// knowledge of `ValueKind`. Introspection of underlying kind is only required
11/// when the configuration values are unstructured or do not have known types.
12#[derive(Debug, Clone, PartialEq)]
13pub enum ValueKind {
14  Nil,
15  Boolean(bool),
16  I64(i64),
17  I128(i128),
18  U64(u64),
19  U128(u128),
20  Float(f64),
21  String(String),
22  Table(Table),
23  Array(Array),
24}
25
26pub type Array = Vec<Value>;
27pub type Table = Map<String, Value>;
28
29impl Default for ValueKind {
30  fn default() -> Self {
31    Self::Nil
32  }
33}
34
35impl<T> From<Option<T>> for ValueKind
36where
37  T: Into<Self>,
38{
39  fn from(value: Option<T>) -> Self {
40    match value {
41      Some(value) => value.into(),
42      None => Self::Nil,
43    }
44  }
45}
46
47impl From<String> for ValueKind {
48  fn from(value: String) -> Self {
49    Self::String(value)
50  }
51}
52
53impl<'a> From<&'a str> for ValueKind {
54  fn from(value: &'a str) -> Self {
55    Self::String(value.into())
56  }
57}
58
59impl From<i8> for ValueKind {
60  fn from(value: i8) -> Self {
61    Self::I64(value.into())
62  }
63}
64
65impl From<i16> for ValueKind {
66  fn from(value: i16) -> Self {
67    Self::I64(value.into())
68  }
69}
70
71impl From<i32> for ValueKind {
72  fn from(value: i32) -> Self {
73    Self::I64(value.into())
74  }
75}
76
77impl From<i64> for ValueKind {
78  fn from(value: i64) -> Self {
79    Self::I64(value)
80  }
81}
82
83impl From<i128> for ValueKind {
84  fn from(value: i128) -> Self {
85    Self::I128(value)
86  }
87}
88
89impl From<u8> for ValueKind {
90  fn from(value: u8) -> Self {
91    Self::U64(value.into())
92  }
93}
94
95impl From<u16> for ValueKind {
96  fn from(value: u16) -> Self {
97    Self::U64(value.into())
98  }
99}
100
101impl From<u32> for ValueKind {
102  fn from(value: u32) -> Self {
103    Self::U64(value.into())
104  }
105}
106
107impl From<u64> for ValueKind {
108  fn from(value: u64) -> Self {
109    Self::U64(value)
110  }
111}
112
113impl From<u128> for ValueKind {
114  fn from(value: u128) -> Self {
115    Self::U128(value)
116  }
117}
118
119impl From<f64> for ValueKind {
120  fn from(value: f64) -> Self {
121    Self::Float(value)
122  }
123}
124
125impl From<bool> for ValueKind {
126  fn from(value: bool) -> Self {
127    Self::Boolean(value)
128  }
129}
130
131impl<T> From<Map<String, T>> for ValueKind
132where
133  T: Into<Value>,
134{
135  fn from(values: Map<String, T>) -> Self {
136    let t = values.into_iter().map(|(k, v)| (k, v.into())).collect();
137    Self::Table(t)
138  }
139}
140
141impl<T> From<Vec<T>> for ValueKind
142where
143  T: Into<Value>,
144{
145  fn from(values: Vec<T>) -> Self {
146    Self::Array(values.into_iter().map(T::into).collect())
147  }
148}
149
150impl Display for ValueKind {
151  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
152    use std::fmt::Write;
153
154    match *self {
155      Self::String(ref value) => write!(f, "{}", value),
156      Self::Boolean(value) => write!(f, "{}", value),
157      Self::I64(value) => write!(f, "{}", value),
158      Self::I128(value) => write!(f, "{}", value),
159      Self::U64(value) => write!(f, "{}", value),
160      Self::U128(value) => write!(f, "{}", value),
161      Self::Float(value) => write!(f, "{}", value),
162      Self::Nil => write!(f, "nil"),
163      Self::Table(ref table) => {
164        let mut s = String::new();
165        for (k, v) in table.iter() {
166          write!(s, "{} => {}, ", k, v)?
167        }
168        write!(f, "{{ {s} }}")
169      }
170      Self::Array(ref array) => {
171        let mut s = String::new();
172        for e in array.iter() {
173          write!(s, "{}, ", e)?;
174        }
175        write!(f, "{s:?}")
176      }
177    }
178  }
179}
180
181/// A configuration value.
182#[derive(Default, Debug, Clone, PartialEq)]
183pub struct Value {
184  /// A description of the original location of the value.
185  ///
186  /// A Value originating from a File might contain:
187  /// ```text
188  /// Settings.toml
189  /// ```
190  ///
191  /// A Value originating from the environment would contain:
192  /// ```text
193  /// the envrionment
194  /// ```
195  ///
196  /// A Value originating from a remote source might contain:
197  /// ```text
198  /// etcd+http://127.0.0.1:2379
199  /// ```
200  origin: Option<String>,
201
202  /// Underlying kind of the configuration value.
203  pub kind: ValueKind,
204}
205
206impl Value {
207  /// Create a new value instance that will remember its source uri.
208  pub fn new<V>(origin: Option<&String>, kind: V) -> Self
209  where
210    V: Into<ValueKind>,
211  {
212    Self { origin: origin.cloned(), kind: kind.into() }
213  }
214
215  /// Get the description of the original location of the value.
216  pub fn origin(&self) -> Option<&str> {
217    self.origin.as_ref().map(AsRef::as_ref)
218  }
219
220  /// Attempt to deserialize this value into the requested type.
221  pub fn try_deserialize<'de, T: Deserialize<'de>>(self) -> Result<T> {
222    T::deserialize(self)
223  }
224
225  /// Returns `self` as a bool, if possible.
226  // FIXME: Should this not be `try_into_*` ?
227  pub fn into_bool(self) -> Result<bool> {
228    match self.kind {
229      ValueKind::Boolean(value) => Ok(value),
230      ValueKind::I64(value) => Ok(value != 0),
231      ValueKind::I128(value) => Ok(value != 0),
232      ValueKind::U64(value) => Ok(value != 0),
233      ValueKind::U128(value) => Ok(value != 0),
234      ValueKind::Float(value) => Ok(value != 0.0),
235
236      ValueKind::String(ref value) => {
237        match value.to_lowercase().as_ref() {
238          "1" | "true" | "on" | "yes" => Ok(true),
239          "0" | "false" | "off" | "no" => Ok(false),
240
241          // Unexpected string value
242          s => Err(ConfigError::invalid_type(
243            self.origin.clone(),
244            Unexpected::Str(s.into()),
245            "a boolean",
246          )),
247        }
248      }
249
250      // Unexpected type
251      ValueKind::Nil => Err(ConfigError::invalid_type(self.origin, Unexpected::Unit, "a boolean")),
252      ValueKind::Table(_) => {
253        Err(ConfigError::invalid_type(self.origin, Unexpected::Map, "a boolean"))
254      }
255      ValueKind::Array(_) => {
256        Err(ConfigError::invalid_type(self.origin, Unexpected::Seq, "a boolean"))
257      }
258    }
259  }
260
261  /// Returns `self` into an i64, if possible.
262  // FIXME: Should this not be `try_into_*` ?
263  pub fn into_int(self) -> Result<i64> {
264    match self.kind {
265      ValueKind::I64(value) => Ok(value),
266      ValueKind::I128(value) => value.try_into().map_err(|_| {
267        ConfigError::invalid_type(
268          self.origin,
269          Unexpected::I128(value),
270          "an signed 64 bit or less integer",
271        )
272      }),
273      ValueKind::U64(value) => value.try_into().map_err(|_| {
274        ConfigError::invalid_type(
275          self.origin,
276          Unexpected::U64(value),
277          "an signed 64 bit or less integer",
278        )
279      }),
280      ValueKind::U128(value) => value.try_into().map_err(|_| {
281        ConfigError::invalid_type(
282          self.origin,
283          Unexpected::U128(value),
284          "an signed 64 bit or less integer",
285        )
286      }),
287
288      ValueKind::String(ref s) => {
289        match s.to_lowercase().as_ref() {
290          "true" | "on" | "yes" => Ok(1),
291          "false" | "off" | "no" => Ok(0),
292          _ => {
293            s.parse().map_err(|_| {
294              // Unexpected string
295              ConfigError::invalid_type(
296                self.origin.clone(),
297                Unexpected::Str(s.clone()),
298                "an integer",
299              )
300            })
301          }
302        }
303      }
304
305      ValueKind::Boolean(value) => Ok(i64::from(value)),
306      ValueKind::Float(value) => Ok(value.round() as i64),
307
308      // Unexpected type
309      ValueKind::Nil => Err(ConfigError::invalid_type(self.origin, Unexpected::Unit, "an integer")),
310      ValueKind::Table(_) => {
311        Err(ConfigError::invalid_type(self.origin, Unexpected::Map, "an integer"))
312      }
313      ValueKind::Array(_) => {
314        Err(ConfigError::invalid_type(self.origin, Unexpected::Seq, "an integer"))
315      }
316    }
317  }
318
319  /// Returns `self` into an i128, if possible.
320  pub fn into_int128(self) -> Result<i128> {
321    match self.kind {
322      ValueKind::I64(value) => Ok(value.into()),
323      ValueKind::I128(value) => Ok(value),
324      ValueKind::U64(value) => Ok(value.into()),
325      ValueKind::U128(value) => value.try_into().map_err(|_| {
326        ConfigError::invalid_type(self.origin, Unexpected::U128(value), "an signed 128 bit integer")
327      }),
328
329      ValueKind::String(ref s) => {
330        match s.to_lowercase().as_ref() {
331          "true" | "on" | "yes" => Ok(1),
332          "false" | "off" | "no" => Ok(0),
333          _ => {
334            s.parse().map_err(|_| {
335              // Unexpected string
336              ConfigError::invalid_type(
337                self.origin.clone(),
338                Unexpected::Str(s.clone()),
339                "an integer",
340              )
341            })
342          }
343        }
344      }
345
346      ValueKind::Boolean(value) => Ok(i128::from(value)),
347      ValueKind::Float(value) => Ok(value.round() as i128),
348
349      // Unexpected type
350      ValueKind::Nil => Err(ConfigError::invalid_type(self.origin, Unexpected::Unit, "an integer")),
351      ValueKind::Table(_) => {
352        Err(ConfigError::invalid_type(self.origin, Unexpected::Map, "an integer"))
353      }
354      ValueKind::Array(_) => {
355        Err(ConfigError::invalid_type(self.origin, Unexpected::Seq, "an integer"))
356      }
357    }
358  }
359
360  /// Returns `self` into an u64, if possible.
361  // FIXME: Should this not be `try_into_*` ?
362  pub fn into_uint(self) -> Result<u64> {
363    match self.kind {
364      ValueKind::U64(value) => Ok(value),
365      ValueKind::U128(value) => value.try_into().map_err(|_| {
366        ConfigError::invalid_type(
367          self.origin,
368          Unexpected::U128(value),
369          "an unsigned 64 bit or less integer",
370        )
371      }),
372      ValueKind::I64(value) => value.try_into().map_err(|_| {
373        ConfigError::invalid_type(
374          self.origin,
375          Unexpected::I64(value),
376          "an unsigned 64 bit or less integer",
377        )
378      }),
379      ValueKind::I128(value) => value.try_into().map_err(|_| {
380        ConfigError::invalid_type(
381          self.origin,
382          Unexpected::I128(value),
383          "an unsigned 64 bit or less integer",
384        )
385      }),
386
387      ValueKind::String(ref s) => {
388        match s.to_lowercase().as_ref() {
389          "true" | "on" | "yes" => Ok(1),
390          "false" | "off" | "no" => Ok(0),
391          _ => {
392            s.parse().map_err(|_| {
393              // Unexpected string
394              ConfigError::invalid_type(
395                self.origin.clone(),
396                Unexpected::Str(s.clone()),
397                "an integer",
398              )
399            })
400          }
401        }
402      }
403
404      ValueKind::Boolean(value) => Ok(u64::from(value)),
405      ValueKind::Float(value) => Ok(value.round() as u64),
406
407      // Unexpected type
408      ValueKind::Nil => Err(ConfigError::invalid_type(self.origin, Unexpected::Unit, "an integer")),
409      ValueKind::Table(_) => {
410        Err(ConfigError::invalid_type(self.origin, Unexpected::Map, "an integer"))
411      }
412      ValueKind::Array(_) => {
413        Err(ConfigError::invalid_type(self.origin, Unexpected::Seq, "an integer"))
414      }
415    }
416  }
417
418  /// Returns `self` into an u128, if possible.
419  pub fn into_uint128(self) -> Result<u128> {
420    match self.kind {
421      ValueKind::U64(value) => Ok(value.into()),
422      ValueKind::U128(value) => Ok(value),
423      ValueKind::I64(value) => value.try_into().map_err(|_| {
424        ConfigError::invalid_type(
425          self.origin,
426          Unexpected::I64(value),
427          "an unsigned 128 bit or less integer",
428        )
429      }),
430      ValueKind::I128(value) => value.try_into().map_err(|_| {
431        ConfigError::invalid_type(
432          self.origin,
433          Unexpected::I128(value),
434          "an unsigned 128 bit or less integer",
435        )
436      }),
437
438      ValueKind::String(ref s) => {
439        match s.to_lowercase().as_ref() {
440          "true" | "on" | "yes" => Ok(1),
441          "false" | "off" | "no" => Ok(0),
442          _ => {
443            s.parse().map_err(|_| {
444              // Unexpected string
445              ConfigError::invalid_type(
446                self.origin.clone(),
447                Unexpected::Str(s.clone()),
448                "an integer",
449              )
450            })
451          }
452        }
453      }
454
455      ValueKind::Boolean(value) => Ok(u128::from(value)),
456      ValueKind::Float(value) => Ok(value.round() as u128),
457
458      // Unexpected type
459      ValueKind::Nil => Err(ConfigError::invalid_type(self.origin, Unexpected::Unit, "an integer")),
460      ValueKind::Table(_) => {
461        Err(ConfigError::invalid_type(self.origin, Unexpected::Map, "an integer"))
462      }
463      ValueKind::Array(_) => {
464        Err(ConfigError::invalid_type(self.origin, Unexpected::Seq, "an integer"))
465      }
466    }
467  }
468
469  /// Returns `self` into a f64, if possible.
470  // FIXME: Should this not be `try_into_*` ?
471  pub fn into_float(self) -> Result<f64> {
472    match self.kind {
473      ValueKind::Float(value) => Ok(value),
474
475      ValueKind::String(ref s) => {
476        match s.to_lowercase().as_ref() {
477          "true" | "on" | "yes" => Ok(1.0),
478          "false" | "off" | "no" => Ok(0.0),
479          _ => {
480            s.parse().map_err(|_| {
481              // Unexpected string
482              ConfigError::invalid_type(
483                self.origin.clone(),
484                Unexpected::Str(s.clone()),
485                "a floating point",
486              )
487            })
488          }
489        }
490      }
491
492      ValueKind::I64(value) => Ok(value as f64),
493      ValueKind::I128(value) => Ok(value as f64),
494      ValueKind::U64(value) => Ok(value as f64),
495      ValueKind::U128(value) => Ok(value as f64),
496      ValueKind::Boolean(value) => Ok(if value { 1.0 } else { 0.0 }),
497
498      // Unexpected type
499      ValueKind::Nil => {
500        Err(ConfigError::invalid_type(self.origin, Unexpected::Unit, "a floating point"))
501      }
502      ValueKind::Table(_) => {
503        Err(ConfigError::invalid_type(self.origin, Unexpected::Map, "a floating point"))
504      }
505      ValueKind::Array(_) => {
506        Err(ConfigError::invalid_type(self.origin, Unexpected::Seq, "a floating point"))
507      }
508    }
509  }
510
511  /// Returns `self` into a string, if possible.
512  // FIXME: Should this not be `try_into_*` ?
513  pub fn into_string(self) -> Result<String> {
514    match self.kind {
515      ValueKind::String(value) => Ok(value),
516
517      ValueKind::Boolean(value) => Ok(value.to_string()),
518      ValueKind::I64(value) => Ok(value.to_string()),
519      ValueKind::I128(value) => Ok(value.to_string()),
520      ValueKind::U64(value) => Ok(value.to_string()),
521      ValueKind::U128(value) => Ok(value.to_string()),
522      ValueKind::Float(value) => Ok(value.to_string()),
523
524      // Cannot convert
525      ValueKind::Nil => Err(ConfigError::invalid_type(self.origin, Unexpected::Unit, "a string")),
526      ValueKind::Table(_) => {
527        Err(ConfigError::invalid_type(self.origin, Unexpected::Map, "a string"))
528      }
529      ValueKind::Array(_) => {
530        Err(ConfigError::invalid_type(self.origin, Unexpected::Seq, "a string"))
531      }
532    }
533  }
534
535  /// Returns `self` into an array, if possible
536  // FIXME: Should this not be `try_into_*` ?
537  pub fn into_array(self) -> Result<Vec<Self>> {
538    match self.kind {
539      ValueKind::Array(value) => Ok(value),
540
541      // Cannot convert
542      ValueKind::Float(value) => {
543        Err(ConfigError::invalid_type(self.origin, Unexpected::Float(value), "an array"))
544      }
545      ValueKind::String(value) => {
546        Err(ConfigError::invalid_type(self.origin, Unexpected::Str(value), "an array"))
547      }
548      ValueKind::I64(value) => {
549        Err(ConfigError::invalid_type(self.origin, Unexpected::I64(value), "an array"))
550      }
551      ValueKind::I128(value) => {
552        Err(ConfigError::invalid_type(self.origin, Unexpected::I128(value), "an array"))
553      }
554      ValueKind::U64(value) => {
555        Err(ConfigError::invalid_type(self.origin, Unexpected::U64(value), "an array"))
556      }
557      ValueKind::U128(value) => {
558        Err(ConfigError::invalid_type(self.origin, Unexpected::U128(value), "an array"))
559      }
560      ValueKind::Boolean(value) => {
561        Err(ConfigError::invalid_type(self.origin, Unexpected::Bool(value), "an array"))
562      }
563      ValueKind::Nil => Err(ConfigError::invalid_type(self.origin, Unexpected::Unit, "an array")),
564      ValueKind::Table(_) => {
565        Err(ConfigError::invalid_type(self.origin, Unexpected::Map, "an array"))
566      }
567    }
568  }
569
570  /// If the `Value` is a Table, returns the associated Map.
571  // FIXME: Should this not be `try_into_*` ?
572  pub fn into_table(self) -> Result<Map<String, Self>> {
573    match self.kind {
574      ValueKind::Table(value) => Ok(value),
575
576      // Cannot convert
577      ValueKind::Float(value) => {
578        Err(ConfigError::invalid_type(self.origin, Unexpected::Float(value), "a map"))
579      }
580      ValueKind::String(value) => {
581        Err(ConfigError::invalid_type(self.origin, Unexpected::Str(value), "a map"))
582      }
583      ValueKind::I64(value) => {
584        Err(ConfigError::invalid_type(self.origin, Unexpected::I64(value), "a map"))
585      }
586      ValueKind::I128(value) => {
587        Err(ConfigError::invalid_type(self.origin, Unexpected::I128(value), "a map"))
588      }
589      ValueKind::U64(value) => {
590        Err(ConfigError::invalid_type(self.origin, Unexpected::U64(value), "a map"))
591      }
592      ValueKind::U128(value) => {
593        Err(ConfigError::invalid_type(self.origin, Unexpected::U128(value), "a map"))
594      }
595      ValueKind::Boolean(value) => {
596        Err(ConfigError::invalid_type(self.origin, Unexpected::Bool(value), "a map"))
597      }
598      ValueKind::Nil => Err(ConfigError::invalid_type(self.origin, Unexpected::Unit, "a map")),
599      ValueKind::Array(_) => Err(ConfigError::invalid_type(self.origin, Unexpected::Seq, "a map")),
600    }
601  }
602}
603
604impl<'de> Deserialize<'de> for Value {
605  #[inline]
606  fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
607  where
608    D: Deserializer<'de>,
609  {
610    struct ValueVisitor;
611
612    impl<'de> Visitor<'de> for ValueVisitor {
613      type Value = Value;
614
615      fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
616        formatter.write_str("any valid configuration value")
617      }
618
619      #[inline]
620      fn visit_bool<E>(self, value: bool) -> ::std::result::Result<Value, E> {
621        Ok(value.into())
622      }
623
624      #[inline]
625      fn visit_i8<E>(self, value: i8) -> ::std::result::Result<Value, E> {
626        Ok((i64::from(value)).into())
627      }
628
629      #[inline]
630      fn visit_i16<E>(self, value: i16) -> ::std::result::Result<Value, E> {
631        Ok((i64::from(value)).into())
632      }
633
634      #[inline]
635      fn visit_i32<E>(self, value: i32) -> ::std::result::Result<Value, E> {
636        Ok((i64::from(value)).into())
637      }
638
639      #[inline]
640      fn visit_i64<E>(self, value: i64) -> ::std::result::Result<Value, E> {
641        Ok(value.into())
642      }
643
644      #[inline]
645      fn visit_i128<E>(self, value: i128) -> ::std::result::Result<Value, E> {
646        Ok(value.into())
647      }
648
649      #[inline]
650      fn visit_u8<E>(self, value: u8) -> ::std::result::Result<Value, E> {
651        Ok((i64::from(value)).into())
652      }
653
654      #[inline]
655      fn visit_u16<E>(self, value: u16) -> ::std::result::Result<Value, E> {
656        Ok((i64::from(value)).into())
657      }
658
659      #[inline]
660      fn visit_u32<E>(self, value: u32) -> ::std::result::Result<Value, E> {
661        Ok((i64::from(value)).into())
662      }
663
664      #[inline]
665      fn visit_u64<E>(self, value: u64) -> ::std::result::Result<Value, E>
666      where
667        E: ::serde::de::Error,
668      {
669        let num: i64 = value
670          .try_into()
671          .map_err(|_| E::invalid_type(::serde::de::Unexpected::Unsigned(value), &self))?;
672        Ok(num.into())
673      }
674
675      #[inline]
676      fn visit_u128<E>(self, value: u128) -> ::std::result::Result<Value, E>
677      where
678        E: ::serde::de::Error,
679      {
680        let num: i128 = value.try_into().map_err(|_| {
681          E::invalid_type(
682            ::serde::de::Unexpected::Other(format!("integer `{}` as u128", value).as_str()),
683            &self,
684          )
685        })?;
686        Ok(num.into())
687      }
688
689      #[inline]
690      fn visit_f64<E>(self, value: f64) -> ::std::result::Result<Value, E> {
691        Ok(value.into())
692      }
693
694      #[inline]
695      fn visit_str<E>(self, value: &str) -> ::std::result::Result<Value, E>
696      where
697        E: ::serde::de::Error,
698      {
699        self.visit_string(String::from(value))
700      }
701
702      #[inline]
703      fn visit_string<E>(self, value: String) -> ::std::result::Result<Value, E> {
704        Ok(value.into())
705      }
706
707      #[inline]
708      fn visit_none<E>(self) -> ::std::result::Result<Value, E> {
709        Ok(Value::new(None, ValueKind::Nil))
710      }
711
712      #[inline]
713      fn visit_some<D>(self, deserializer: D) -> ::std::result::Result<Value, D::Error>
714      where
715        D: Deserializer<'de>,
716      {
717        Deserialize::deserialize(deserializer)
718      }
719
720      #[inline]
721      fn visit_unit<E>(self) -> ::std::result::Result<Value, E> {
722        Ok(Value::new(None, ValueKind::Nil))
723      }
724
725      #[inline]
726      fn visit_seq<V>(self, mut visitor: V) -> ::std::result::Result<Value, V::Error>
727      where
728        V: ::serde::de::SeqAccess<'de>,
729      {
730        let mut vec = Array::new();
731
732        while let Some(elem) = visitor.next_element()? {
733          vec.push(elem);
734        }
735
736        Ok(vec.into())
737      }
738
739      fn visit_map<V>(self, mut visitor: V) -> ::std::result::Result<Value, V::Error>
740      where
741        V: ::serde::de::MapAccess<'de>,
742      {
743        let mut values = Table::new();
744
745        while let Some((key, value)) = visitor.next_entry()? {
746          values.insert(key, value);
747        }
748
749        Ok(values.into())
750      }
751    }
752
753    deserializer.deserialize_any(ValueVisitor)
754  }
755}
756
757impl<T> From<T> for Value
758where
759  T: Into<ValueKind>,
760{
761  fn from(value: T) -> Self {
762    Self { origin: None, kind: value.into() }
763  }
764}
765
766impl Display for Value {
767  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
768    write!(f, "{}", self.kind)
769  }
770}