esp_config/generate/
value.rs1use std::fmt;
2
3use serde::{Deserialize, Serialize};
4
5use super::Error;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
9pub enum Value {
10 Bool(bool),
12 Integer(i128),
14 String(String),
16}
17
18impl Serialize for Value {
19 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
20 where
21 S: serde::Serializer,
22 {
23 match self {
24 Value::String(s) => serializer.serialize_str(&format!("\"{s}\"")),
25 Value::Integer(n) => serializer.serialize_str(&format!("{n}")),
26 Value::Bool(b) => serializer.serialize_str(&format!("{b}")),
27 }
28 }
29}
30
31impl<'de> Deserialize<'de> for Value {
32 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
33 where
34 D: serde::Deserializer<'de>,
35 {
36 struct ValueVisitor;
37
38 impl serde::de::Visitor<'_> for ValueVisitor {
39 type Value = String;
40
41 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 formatter.write_str("a String representing the Value")
43 }
44
45 fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
46 where
47 E: serde::de::Error,
48 {
49 Ok(v)
50 }
51
52 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
53 where
54 E: serde::de::Error,
55 {
56 Ok(v.to_string())
57 }
58 }
59
60 let str_repr = deserializer.deserialize_string(ValueVisitor)?;
61 let str_repr = str_repr.as_str();
62
63 if let Some(remaining) = str_repr.strip_prefix("\"") {
64 let s = &remaining[..remaining.len() - 1];
65 return Ok(Value::String(s.to_string()));
66 }
67
68 if str_repr == "true" {
69 return Ok(Value::Bool(true));
70 }
71
72 if str_repr == "false" {
73 return Ok(Value::Bool(false));
74 }
75
76 Ok(Value::Integer(str_repr.parse().map_err(
77 |e: core::num::ParseIntError| serde::de::Error::custom(e.to_string()),
78 )?))
79 }
80}
81
82impl Value {
84 pub fn parse_in_place(&mut self, s: &str) -> Result<(), Error> {
86 *self = match self {
87 Value::Bool(_) => match s {
88 "true" => Value::Bool(true),
89 "false" => Value::Bool(false),
90 _ => {
91 return Err(Error::parse(format!(
92 "Expected 'true' or 'false', found: '{s}'"
93 )));
94 }
95 },
96 Value::Integer(_) => {
97 let inner = match s.as_bytes() {
98 [b'0', b'x', ..] => i128::from_str_radix(&s[2..], 16),
99 [b'0', b'o', ..] => i128::from_str_radix(&s[2..], 8),
100 [b'0', b'b', ..] => i128::from_str_radix(&s[2..], 2),
101 _ => s.parse(),
102 }
103 .map_err(|_| Error::parse(format!("Expected valid intger value, found: '{s}'")))?;
104
105 Value::Integer(inner)
106 }
107 Value::String(_) => Value::String(s.into()),
108 };
109
110 Ok(())
111 }
112
113 pub fn as_bool(&self) -> bool {
115 match self {
116 Value::Bool(value) => *value,
117 _ => panic!("attempted to convert non-bool value to a bool"),
118 }
119 }
120
121 pub fn as_integer(&self) -> i128 {
123 match self {
124 Value::Integer(value) => *value,
125 _ => panic!("attempted to convert non-integer value to an integer"),
126 }
127 }
128
129 pub fn as_string(&self) -> String {
131 match self {
132 Value::String(value) => value.to_owned(),
133 _ => panic!("attempted to convert non-string value to a string"),
134 }
135 }
136
137 pub fn is_bool(&self) -> bool {
139 matches!(self, Value::Bool(_))
140 }
141
142 pub fn is_integer(&self) -> bool {
144 matches!(self, Value::Integer(_))
145 }
146
147 pub fn is_string(&self) -> bool {
149 matches!(self, Value::String(_))
150 }
151}
152
153impl fmt::Display for Value {
154 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155 match self {
156 Value::Bool(b) => write!(f, "{b}"),
157 Value::Integer(i) => write!(f, "{i}"),
158 Value::String(s) => write!(f, "{s}"),
159 }
160 }
161}
162
163impl From<bool> for Value {
164 fn from(value: bool) -> Self {
165 Value::Bool(value)
166 }
167}
168
169impl From<i128> for Value {
170 fn from(value: i128) -> Self {
171 Value::Integer(value)
172 }
173}
174
175impl From<&str> for Value {
176 fn from(value: &str) -> Self {
177 Value::String(value.to_string())
178 }
179}
180
181impl From<String> for Value {
182 fn from(value: String) -> Self {
183 Value::String(value)
184 }
185}
186
187#[cfg(test)]
188mod test {
189 use super::*;
190
191 #[test]
192 fn deserialization_number() {
193 assert_eq!(
194 serde_yaml::from_str::<Value>("128").unwrap(),
195 Value::Integer(128)
196 );
197 assert_eq!(
198 serde_yaml::from_str::<Value>(&format!("{}", i128::MAX)).unwrap(),
199 Value::Integer(i128::MAX)
200 );
201 assert_eq!(
202 serde_yaml::from_str::<Value>(&format!("{}", i128::MIN)).unwrap(),
203 Value::Integer(i128::MIN)
204 );
205 }
206
207 #[test]
208 fn deserialization_string() {
209 let yml = "'\"Hello\"'";
210 let value: Value = serde_yaml::from_str(yml).unwrap();
211 assert_eq!(value, Value::String("Hello".to_string()));
212 }
213}