esp_config/generate/
value.rs

1use std::fmt;
2
3use serde::{Deserialize, Serialize};
4
5use super::Error;
6
7/// Supported configuration value types.
8#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
9pub enum Value {
10    /// Booleans.
11    Bool(bool),
12    /// Integers.
13    Integer(i128),
14    /// Strings.
15    String(String),
16}
17
18// TODO: Do we want to handle negative values for non-decimal values?
19impl Value {
20    pub(crate) fn parse_in_place(&mut self, s: &str) -> Result<(), Error> {
21        *self = match self {
22            Value::Bool(_) => match s {
23                "true" => Value::Bool(true),
24                "false" => Value::Bool(false),
25                _ => {
26                    return Err(Error::parse(format!(
27                        "Expected 'true' or 'false', found: '{s}'"
28                    )));
29                }
30            },
31            Value::Integer(_) => {
32                let inner = match s.as_bytes() {
33                    [b'0', b'x', ..] => i128::from_str_radix(&s[2..], 16),
34                    [b'0', b'o', ..] => i128::from_str_radix(&s[2..], 8),
35                    [b'0', b'b', ..] => i128::from_str_radix(&s[2..], 2),
36                    _ => s.parse(),
37                }
38                .map_err(|_| Error::parse(format!("Expected valid intger value, found: '{s}'")))?;
39
40                Value::Integer(inner)
41            }
42            Value::String(_) => Value::String(s.into()),
43        };
44
45        Ok(())
46    }
47
48    /// Convert the value to a [bool].
49    pub fn as_bool(&self) -> bool {
50        match self {
51            Value::Bool(value) => *value,
52            _ => panic!("attempted to convert non-bool value to a bool"),
53        }
54    }
55
56    /// Convert the value to an [i128].
57    pub fn as_integer(&self) -> i128 {
58        match self {
59            Value::Integer(value) => *value,
60            _ => panic!("attempted to convert non-integer value to an integer"),
61        }
62    }
63
64    /// Convert the value to a [String].
65    pub fn as_string(&self) -> String {
66        match self {
67            Value::String(value) => value.to_owned(),
68            _ => panic!("attempted to convert non-string value to a string"),
69        }
70    }
71
72    /// Is the value a bool?
73    pub fn is_bool(&self) -> bool {
74        matches!(self, Value::Bool(_))
75    }
76
77    /// Is the value an integer?
78    pub fn is_integer(&self) -> bool {
79        matches!(self, Value::Integer(_))
80    }
81
82    /// Is the value a string?
83    pub fn is_string(&self) -> bool {
84        matches!(self, Value::String(_))
85    }
86}
87
88impl fmt::Display for Value {
89    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90        match self {
91            Value::Bool(b) => write!(f, "{b}"),
92            Value::Integer(i) => write!(f, "{i}"),
93            Value::String(s) => write!(f, "{s}"),
94        }
95    }
96}
97
98impl From<bool> for Value {
99    fn from(value: bool) -> Self {
100        Value::Bool(value)
101    }
102}
103
104impl From<i128> for Value {
105    fn from(value: i128) -> Self {
106        Value::Integer(value)
107    }
108}
109
110impl From<&str> for Value {
111    fn from(value: &str) -> Self {
112        Value::String(value.to_string())
113    }
114}
115
116impl From<String> for Value {
117    fn from(value: String) -> Self {
118        Value::String(value)
119    }
120}