1use std::convert::TryInto;
2use std::fmt;
3use std::fmt::Display;
4
5use serde_core::de::{Deserialize, Deserializer, Visitor};
6
7use crate::error::{ConfigError, Result, Unexpected};
8use crate::map::Map;
9
10#[derive(Debug, Clone, PartialEq, Default)]
16pub enum ValueKind {
17 #[default]
18 Nil,
19 Boolean(bool),
20 I64(i64),
21 I128(i128),
22 U64(u64),
23 U128(u128),
24 Float(f64),
25 String(String),
26 Table(Table),
27 Array(Array),
28}
29
30pub(crate) type Array = Vec<Value>;
31pub(crate) type Table = Map<String, Value>;
32
33impl<T> From<Option<T>> for ValueKind
34where
35 T: Into<Self>,
36{
37 fn from(value: Option<T>) -> Self {
38 match value {
39 Some(value) => value.into(),
40 None => Self::Nil,
41 }
42 }
43}
44
45impl From<String> for ValueKind {
46 fn from(value: String) -> Self {
47 Self::String(value)
48 }
49}
50
51impl<'a> From<&'a str> for ValueKind {
52 fn from(value: &'a str) -> Self {
53 Self::String(value.into())
54 }
55}
56
57impl From<i8> for ValueKind {
58 fn from(value: i8) -> Self {
59 Self::I64(value.into())
60 }
61}
62
63impl From<i16> for ValueKind {
64 fn from(value: i16) -> Self {
65 Self::I64(value.into())
66 }
67}
68
69impl From<i32> for ValueKind {
70 fn from(value: i32) -> Self {
71 Self::I64(value.into())
72 }
73}
74
75impl From<i64> for ValueKind {
76 fn from(value: i64) -> Self {
77 Self::I64(value)
78 }
79}
80
81impl From<i128> for ValueKind {
82 fn from(value: i128) -> Self {
83 Self::I128(value)
84 }
85}
86
87impl From<u8> for ValueKind {
88 fn from(value: u8) -> Self {
89 Self::U64(value.into())
90 }
91}
92
93impl From<u16> for ValueKind {
94 fn from(value: u16) -> Self {
95 Self::U64(value.into())
96 }
97}
98
99impl From<u32> for ValueKind {
100 fn from(value: u32) -> Self {
101 Self::U64(value.into())
102 }
103}
104
105impl From<u64> for ValueKind {
106 fn from(value: u64) -> Self {
107 Self::U64(value)
108 }
109}
110
111impl From<u128> for ValueKind {
112 fn from(value: u128) -> Self {
113 Self::U128(value)
114 }
115}
116
117impl From<f64> for ValueKind {
118 fn from(value: f64) -> Self {
119 Self::Float(value)
120 }
121}
122
123impl From<bool> for ValueKind {
124 fn from(value: bool) -> Self {
125 Self::Boolean(value)
126 }
127}
128
129impl<T> From<Map<String, T>> for ValueKind
130where
131 T: Into<Value>,
132{
133 fn from(values: Map<String, T>) -> Self {
134 let t = values.into_iter().map(|(k, v)| (k, v.into())).collect();
135 Self::Table(t)
136 }
137}
138
139impl<T> From<Vec<T>> for ValueKind
140where
141 T: Into<Value>,
142{
143 fn from(values: Vec<T>) -> Self {
144 Self::Array(values.into_iter().map(T::into).collect())
145 }
146}
147
148impl Display for ValueKind {
149 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
150 use std::fmt::Write;
151
152 match *self {
153 Self::String(ref value) => write!(f, "{value}"),
154 Self::Boolean(value) => write!(f, "{value}"),
155 Self::I64(value) => write!(f, "{value}"),
156 Self::I128(value) => write!(f, "{value}"),
157 Self::U64(value) => write!(f, "{value}"),
158 Self::U128(value) => write!(f, "{value}"),
159 Self::Float(value) => write!(f, "{value}"),
160 Self::Nil => write!(f, "nil"),
161 Self::Table(ref table) => {
162 let mut s = String::new();
163 for (k, v) in table.iter() {
164 write!(s, "{k} => {v}, ")?;
165 }
166 write!(f, "{{ {s} }}")
167 }
168 Self::Array(ref array) => {
169 let mut s = String::new();
170 for e in array.iter() {
171 write!(s, "{e}, ")?;
172 }
173 write!(f, "{s:?}")
174 }
175 }
176 }
177}
178
179#[derive(Default, Debug, Clone, PartialEq)]
181pub struct Value {
182 origin: Option<String>,
199
200 pub kind: ValueKind,
202}
203
204impl Value {
205 pub fn new<V>(origin: Option<&String>, kind: V) -> Self
207 where
208 V: Into<ValueKind>,
209 {
210 Self {
211 origin: origin.cloned(),
212 kind: kind.into(),
213 }
214 }
215
216 pub fn origin(&self) -> Option<&str> {
218 self.origin.as_ref().map(AsRef::as_ref)
219 }
220
221 pub fn try_deserialize<'de, T: Deserialize<'de>>(self) -> Result<T> {
223 T::deserialize(self)
224 }
225
226 pub fn into_bool(self) -> Result<bool> {
229 match self.kind {
230 ValueKind::Boolean(value) => Ok(value),
231 ValueKind::I64(value) => Ok(value != 0),
232 ValueKind::I128(value) => Ok(value != 0),
233 ValueKind::U64(value) => Ok(value != 0),
234 ValueKind::U128(value) => Ok(value != 0),
235 ValueKind::Float(value) => Ok(value != 0.0),
236
237 ValueKind::String(ref value) => {
238 match value.to_lowercase().as_ref() {
239 "1" | "true" | "on" | "yes" => Ok(true),
240 "0" | "false" | "off" | "no" => Ok(false),
241
242 s => Err(ConfigError::invalid_type(
244 self.origin.clone(),
245 Unexpected::Str(s.into()),
246 "a boolean",
247 )),
248 }
249 }
250
251 ValueKind::Nil => Err(ConfigError::invalid_type(
253 self.origin,
254 Unexpected::Unit,
255 "a boolean",
256 )),
257 ValueKind::Table(_) => Err(ConfigError::invalid_type(
258 self.origin,
259 Unexpected::Map,
260 "a boolean",
261 )),
262 ValueKind::Array(_) => Err(ConfigError::invalid_type(
263 self.origin,
264 Unexpected::Seq,
265 "a boolean",
266 )),
267 }
268 }
269
270 pub fn into_int(self) -> Result<i64> {
273 match self.kind {
274 ValueKind::I64(value) => Ok(value),
275 ValueKind::I128(value) => value.try_into().map_err(|_| {
276 ConfigError::invalid_type(
277 self.origin,
278 Unexpected::I128(value),
279 "an signed 64 bit or less integer",
280 )
281 }),
282 ValueKind::U64(value) => value.try_into().map_err(|_| {
283 ConfigError::invalid_type(
284 self.origin,
285 Unexpected::U64(value),
286 "an signed 64 bit or less integer",
287 )
288 }),
289 ValueKind::U128(value) => value.try_into().map_err(|_| {
290 ConfigError::invalid_type(
291 self.origin,
292 Unexpected::U128(value),
293 "an signed 64 bit or less integer",
294 )
295 }),
296
297 ValueKind::String(ref s) => {
298 match s.to_lowercase().as_ref() {
299 "true" | "on" | "yes" => Ok(1),
300 "false" | "off" | "no" => Ok(0),
301 _ => {
302 s.parse().map_err(|_| {
303 ConfigError::invalid_type(
305 self.origin.clone(),
306 Unexpected::Str(s.clone()),
307 "an integer",
308 )
309 })
310 }
311 }
312 }
313
314 ValueKind::Boolean(value) => Ok(i64::from(value)),
315 ValueKind::Float(value) => Ok(value.round() as i64),
316
317 ValueKind::Nil => Err(ConfigError::invalid_type(
319 self.origin,
320 Unexpected::Unit,
321 "an integer",
322 )),
323 ValueKind::Table(_) => Err(ConfigError::invalid_type(
324 self.origin,
325 Unexpected::Map,
326 "an integer",
327 )),
328 ValueKind::Array(_) => Err(ConfigError::invalid_type(
329 self.origin,
330 Unexpected::Seq,
331 "an integer",
332 )),
333 }
334 }
335
336 pub fn into_int128(self) -> Result<i128> {
338 match self.kind {
339 ValueKind::I64(value) => Ok(value.into()),
340 ValueKind::I128(value) => Ok(value),
341 ValueKind::U64(value) => Ok(value.into()),
342 ValueKind::U128(value) => value.try_into().map_err(|_| {
343 ConfigError::invalid_type(
344 self.origin,
345 Unexpected::U128(value),
346 "an signed 128 bit integer",
347 )
348 }),
349
350 ValueKind::String(ref s) => {
351 match s.to_lowercase().as_ref() {
352 "true" | "on" | "yes" => Ok(1),
353 "false" | "off" | "no" => Ok(0),
354 _ => {
355 s.parse().map_err(|_| {
356 ConfigError::invalid_type(
358 self.origin.clone(),
359 Unexpected::Str(s.clone()),
360 "an integer",
361 )
362 })
363 }
364 }
365 }
366
367 ValueKind::Boolean(value) => Ok(i128::from(value)),
368 ValueKind::Float(value) => Ok(value.round() as i128),
369
370 ValueKind::Nil => Err(ConfigError::invalid_type(
372 self.origin,
373 Unexpected::Unit,
374 "an integer",
375 )),
376 ValueKind::Table(_) => Err(ConfigError::invalid_type(
377 self.origin,
378 Unexpected::Map,
379 "an integer",
380 )),
381 ValueKind::Array(_) => Err(ConfigError::invalid_type(
382 self.origin,
383 Unexpected::Seq,
384 "an integer",
385 )),
386 }
387 }
388
389 pub fn into_uint(self) -> Result<u64> {
392 match self.kind {
393 ValueKind::U64(value) => Ok(value),
394 ValueKind::U128(value) => value.try_into().map_err(|_| {
395 ConfigError::invalid_type(
396 self.origin,
397 Unexpected::U128(value),
398 "an unsigned 64 bit or less integer",
399 )
400 }),
401 ValueKind::I64(value) => value.try_into().map_err(|_| {
402 ConfigError::invalid_type(
403 self.origin,
404 Unexpected::I64(value),
405 "an unsigned 64 bit or less integer",
406 )
407 }),
408 ValueKind::I128(value) => value.try_into().map_err(|_| {
409 ConfigError::invalid_type(
410 self.origin,
411 Unexpected::I128(value),
412 "an unsigned 64 bit or less integer",
413 )
414 }),
415
416 ValueKind::String(ref s) => {
417 match s.to_lowercase().as_ref() {
418 "true" | "on" | "yes" => Ok(1),
419 "false" | "off" | "no" => Ok(0),
420 _ => {
421 s.parse().map_err(|_| {
422 ConfigError::invalid_type(
424 self.origin.clone(),
425 Unexpected::Str(s.clone()),
426 "an integer",
427 )
428 })
429 }
430 }
431 }
432
433 ValueKind::Boolean(value) => Ok(u64::from(value)),
434 ValueKind::Float(value) => Ok(value.round() as u64),
435
436 ValueKind::Nil => Err(ConfigError::invalid_type(
438 self.origin,
439 Unexpected::Unit,
440 "an integer",
441 )),
442 ValueKind::Table(_) => Err(ConfigError::invalid_type(
443 self.origin,
444 Unexpected::Map,
445 "an integer",
446 )),
447 ValueKind::Array(_) => Err(ConfigError::invalid_type(
448 self.origin,
449 Unexpected::Seq,
450 "an integer",
451 )),
452 }
453 }
454
455 pub fn into_uint128(self) -> Result<u128> {
457 match self.kind {
458 ValueKind::U64(value) => Ok(value.into()),
459 ValueKind::U128(value) => Ok(value),
460 ValueKind::I64(value) => value.try_into().map_err(|_| {
461 ConfigError::invalid_type(
462 self.origin,
463 Unexpected::I64(value),
464 "an unsigned 128 bit or less integer",
465 )
466 }),
467 ValueKind::I128(value) => value.try_into().map_err(|_| {
468 ConfigError::invalid_type(
469 self.origin,
470 Unexpected::I128(value),
471 "an unsigned 128 bit or less integer",
472 )
473 }),
474
475 ValueKind::String(ref s) => {
476 match s.to_lowercase().as_ref() {
477 "true" | "on" | "yes" => Ok(1),
478 "false" | "off" | "no" => Ok(0),
479 _ => {
480 s.parse().map_err(|_| {
481 ConfigError::invalid_type(
483 self.origin.clone(),
484 Unexpected::Str(s.clone()),
485 "an integer",
486 )
487 })
488 }
489 }
490 }
491
492 ValueKind::Boolean(value) => Ok(u128::from(value)),
493 ValueKind::Float(value) => Ok(value.round() as u128),
494
495 ValueKind::Nil => Err(ConfigError::invalid_type(
497 self.origin,
498 Unexpected::Unit,
499 "an integer",
500 )),
501 ValueKind::Table(_) => Err(ConfigError::invalid_type(
502 self.origin,
503 Unexpected::Map,
504 "an integer",
505 )),
506 ValueKind::Array(_) => Err(ConfigError::invalid_type(
507 self.origin,
508 Unexpected::Seq,
509 "an integer",
510 )),
511 }
512 }
513
514 pub fn into_float(self) -> Result<f64> {
517 match self.kind {
518 ValueKind::Float(value) => Ok(value),
519
520 ValueKind::String(ref s) => {
521 match s.to_lowercase().as_ref() {
522 "true" | "on" | "yes" => Ok(1.0),
523 "false" | "off" | "no" => Ok(0.0),
524 _ => {
525 s.parse().map_err(|_| {
526 ConfigError::invalid_type(
528 self.origin.clone(),
529 Unexpected::Str(s.clone()),
530 "a floating point",
531 )
532 })
533 }
534 }
535 }
536
537 ValueKind::I64(value) => Ok(value as f64),
538 ValueKind::I128(value) => Ok(value as f64),
539 ValueKind::U64(value) => Ok(value as f64),
540 ValueKind::U128(value) => Ok(value as f64),
541 ValueKind::Boolean(value) => Ok(if value { 1.0 } else { 0.0 }),
542
543 ValueKind::Nil => Err(ConfigError::invalid_type(
545 self.origin,
546 Unexpected::Unit,
547 "a floating point",
548 )),
549 ValueKind::Table(_) => Err(ConfigError::invalid_type(
550 self.origin,
551 Unexpected::Map,
552 "a floating point",
553 )),
554 ValueKind::Array(_) => Err(ConfigError::invalid_type(
555 self.origin,
556 Unexpected::Seq,
557 "a floating point",
558 )),
559 }
560 }
561
562 pub fn into_string(self) -> Result<String> {
565 match self.kind {
566 ValueKind::String(value) => Ok(value),
567
568 ValueKind::Boolean(value) => Ok(value.to_string()),
569 ValueKind::I64(value) => Ok(value.to_string()),
570 ValueKind::I128(value) => Ok(value.to_string()),
571 ValueKind::U64(value) => Ok(value.to_string()),
572 ValueKind::U128(value) => Ok(value.to_string()),
573 ValueKind::Float(value) => Ok(value.to_string()),
574
575 ValueKind::Nil => Err(ConfigError::invalid_type(
577 self.origin,
578 Unexpected::Unit,
579 "a string",
580 )),
581 ValueKind::Table(_) => Err(ConfigError::invalid_type(
582 self.origin,
583 Unexpected::Map,
584 "a string",
585 )),
586 ValueKind::Array(_) => Err(ConfigError::invalid_type(
587 self.origin,
588 Unexpected::Seq,
589 "a string",
590 )),
591 }
592 }
593
594 pub fn into_array(self) -> Result<Vec<Self>> {
597 match self.kind {
598 ValueKind::Array(value) => Ok(value),
599
600 ValueKind::Float(value) => Err(ConfigError::invalid_type(
602 self.origin,
603 Unexpected::Float(value),
604 "an array",
605 )),
606 ValueKind::String(value) => Err(ConfigError::invalid_type(
607 self.origin,
608 Unexpected::Str(value),
609 "an array",
610 )),
611 ValueKind::I64(value) => Err(ConfigError::invalid_type(
612 self.origin,
613 Unexpected::I64(value),
614 "an array",
615 )),
616 ValueKind::I128(value) => Err(ConfigError::invalid_type(
617 self.origin,
618 Unexpected::I128(value),
619 "an array",
620 )),
621 ValueKind::U64(value) => Err(ConfigError::invalid_type(
622 self.origin,
623 Unexpected::U64(value),
624 "an array",
625 )),
626 ValueKind::U128(value) => Err(ConfigError::invalid_type(
627 self.origin,
628 Unexpected::U128(value),
629 "an array",
630 )),
631 ValueKind::Boolean(value) => Err(ConfigError::invalid_type(
632 self.origin,
633 Unexpected::Bool(value),
634 "an array",
635 )),
636 ValueKind::Nil => Err(ConfigError::invalid_type(
637 self.origin,
638 Unexpected::Unit,
639 "an array",
640 )),
641 ValueKind::Table(_) => Err(ConfigError::invalid_type(
642 self.origin,
643 Unexpected::Map,
644 "an array",
645 )),
646 }
647 }
648
649 pub fn into_table(self) -> Result<Map<String, Self>> {
652 match self.kind {
653 ValueKind::Table(value) => Ok(value),
654
655 ValueKind::Float(value) => Err(ConfigError::invalid_type(
657 self.origin,
658 Unexpected::Float(value),
659 "a map",
660 )),
661 ValueKind::String(value) => Err(ConfigError::invalid_type(
662 self.origin,
663 Unexpected::Str(value),
664 "a map",
665 )),
666 ValueKind::I64(value) => Err(ConfigError::invalid_type(
667 self.origin,
668 Unexpected::I64(value),
669 "a map",
670 )),
671 ValueKind::I128(value) => Err(ConfigError::invalid_type(
672 self.origin,
673 Unexpected::I128(value),
674 "a map",
675 )),
676 ValueKind::U64(value) => Err(ConfigError::invalid_type(
677 self.origin,
678 Unexpected::U64(value),
679 "a map",
680 )),
681 ValueKind::U128(value) => Err(ConfigError::invalid_type(
682 self.origin,
683 Unexpected::U128(value),
684 "a map",
685 )),
686 ValueKind::Boolean(value) => Err(ConfigError::invalid_type(
687 self.origin,
688 Unexpected::Bool(value),
689 "a map",
690 )),
691 ValueKind::Nil => Err(ConfigError::invalid_type(
692 self.origin,
693 Unexpected::Unit,
694 "a map",
695 )),
696 ValueKind::Array(_) => Err(ConfigError::invalid_type(
697 self.origin,
698 Unexpected::Seq,
699 "a map",
700 )),
701 }
702 }
703}
704
705impl<'de> Deserialize<'de> for Value {
706 #[inline]
707 fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
708 where
709 D: Deserializer<'de>,
710 {
711 struct ValueVisitor;
712
713 impl<'de> Visitor<'de> for ValueVisitor {
714 type Value = Value;
715
716 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
717 formatter.write_str("any valid configuration value")
718 }
719
720 #[inline]
721 fn visit_bool<E>(self, value: bool) -> ::std::result::Result<Value, E> {
722 Ok(value.into())
723 }
724
725 #[inline]
726 fn visit_i8<E>(self, value: i8) -> ::std::result::Result<Value, E> {
727 Ok((i64::from(value)).into())
728 }
729
730 #[inline]
731 fn visit_i16<E>(self, value: i16) -> ::std::result::Result<Value, E> {
732 Ok((i64::from(value)).into())
733 }
734
735 #[inline]
736 fn visit_i32<E>(self, value: i32) -> ::std::result::Result<Value, E> {
737 Ok((i64::from(value)).into())
738 }
739
740 #[inline]
741 fn visit_i64<E>(self, value: i64) -> ::std::result::Result<Value, E> {
742 Ok(value.into())
743 }
744
745 #[inline]
746 fn visit_i128<E>(self, value: i128) -> ::std::result::Result<Value, E> {
747 Ok(value.into())
748 }
749
750 #[inline]
751 fn visit_u8<E>(self, value: u8) -> ::std::result::Result<Value, E> {
752 Ok((i64::from(value)).into())
753 }
754
755 #[inline]
756 fn visit_u16<E>(self, value: u16) -> ::std::result::Result<Value, E> {
757 Ok((i64::from(value)).into())
758 }
759
760 #[inline]
761 fn visit_u32<E>(self, value: u32) -> ::std::result::Result<Value, E> {
762 Ok((i64::from(value)).into())
763 }
764
765 #[inline]
766 fn visit_u64<E>(self, value: u64) -> ::std::result::Result<Value, E>
767 where
768 E: ::serde_core::de::Error,
769 {
770 let num: i64 = value.try_into().map_err(|_| {
771 E::invalid_type(::serde_core::de::Unexpected::Unsigned(value), &self)
772 })?;
773 Ok(num.into())
774 }
775
776 #[inline]
777 fn visit_u128<E>(self, value: u128) -> ::std::result::Result<Value, E>
778 where
779 E: ::serde_core::de::Error,
780 {
781 let num: i128 = value.try_into().map_err(|_| {
782 E::invalid_type(
783 ::serde_core::de::Unexpected::Other(
784 format!("integer `{value}` as u128").as_str(),
785 ),
786 &self,
787 )
788 })?;
789 Ok(num.into())
790 }
791
792 #[inline]
793 fn visit_f64<E>(self, value: f64) -> ::std::result::Result<Value, E> {
794 Ok(value.into())
795 }
796
797 #[inline]
798 fn visit_str<E>(self, value: &str) -> ::std::result::Result<Value, E>
799 where
800 E: ::serde_core::de::Error,
801 {
802 self.visit_string(String::from(value))
803 }
804
805 #[inline]
806 fn visit_string<E>(self, value: String) -> ::std::result::Result<Value, E> {
807 Ok(value.into())
808 }
809
810 #[inline]
811 fn visit_none<E>(self) -> ::std::result::Result<Value, E> {
812 Ok(Value::new(None, ValueKind::Nil))
813 }
814
815 #[inline]
816 fn visit_some<D>(self, deserializer: D) -> ::std::result::Result<Value, D::Error>
817 where
818 D: Deserializer<'de>,
819 {
820 Deserialize::deserialize(deserializer)
821 }
822
823 #[inline]
824 fn visit_unit<E>(self) -> ::std::result::Result<Value, E> {
825 Ok(Value::new(None, ValueKind::Nil))
826 }
827
828 #[inline]
829 fn visit_seq<V>(self, mut visitor: V) -> ::std::result::Result<Value, V::Error>
830 where
831 V: ::serde_core::de::SeqAccess<'de>,
832 {
833 let mut vec = Array::new();
834
835 while let Some(elem) = visitor.next_element()? {
836 vec.push(elem);
837 }
838
839 Ok(vec.into())
840 }
841
842 fn visit_map<V>(self, mut visitor: V) -> ::std::result::Result<Value, V::Error>
843 where
844 V: ::serde_core::de::MapAccess<'de>,
845 {
846 let mut values = Table::new();
847
848 while let Some((key, value)) = visitor.next_entry()? {
849 values.insert(key, value);
850 }
851
852 Ok(values.into())
853 }
854 }
855
856 deserializer.deserialize_any(ValueVisitor)
857 }
858}
859
860impl<T> From<T> for Value
861where
862 T: Into<ValueKind>,
863{
864 fn from(value: T) -> Self {
865 Self {
866 origin: None,
867 kind: value.into(),
868 }
869 }
870}
871
872impl Display for Value {
873 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
874 write!(f, "{}", self.kind)
875 }
876}
877
878#[cfg(test)]
879mod tests {
880 use super::ValueKind;
881 use crate::Config;
882 use crate::File;
883 use crate::FileFormat;
884
885 #[test]
886 #[cfg(feature = "toml")]
887 fn test_i64() {
888 let c = Config::builder()
889 .add_source(File::from_str(
890 "
891value = 120
892",
893 FileFormat::Toml,
894 ))
895 .build()
896 .unwrap();
897
898 assert!(std::matches!(c.cache.kind, ValueKind::Table(_)));
899 let v = match c.cache.kind {
900 ValueKind::Table(t) => t,
901 _ => unreachable!(),
902 };
903
904 let value = v.get("value").unwrap();
905 assert!(
906 std::matches!(value.kind, ValueKind::I64(120)),
907 "Is not a i64(120): {:?}",
908 value.kind
909 );
910 }
911}