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#[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#[derive(Default, Debug, Clone, PartialEq)]
183pub struct Value {
184 origin: Option<String>,
201
202 pub kind: ValueKind,
204}
205
206impl Value {
207 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 pub fn origin(&self) -> Option<&str> {
217 self.origin.as_ref().map(AsRef::as_ref)
218 }
219
220 pub fn try_deserialize<'de, T: Deserialize<'de>>(self) -> Result<T> {
222 T::deserialize(self)
223 }
224
225 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 s => Err(ConfigError::invalid_type(
243 self.origin.clone(),
244 Unexpected::Str(s.into()),
245 "a boolean",
246 )),
247 }
248 }
249
250 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 pub fn into_array(self) -> Result<Vec<Self>> {
538 match self.kind {
539 ValueKind::Array(value) => Ok(value),
540
541 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 pub fn into_table(self) -> Result<Map<String, Self>> {
573 match self.kind {
574 ValueKind::Table(value) => Ok(value),
575
576 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}