1use std::borrow::Cow;
2use std::cmp::Ordering;
3use std::collections::BTreeMap;
4use std::hash::Hash;
5use std::net::{AddrParseError, IpAddr};
6use std::result::Result as StdResult;
7use std::str::FromStr;
8
9use serde_json::{Number, Value as JsonValue};
10
11#[derive(Default, Debug, Clone, PartialEq, Eq, Hash)]
13pub enum Value<'a> {
14 #[default]
15 None,
16 String(Cow<'a, str>),
17 Number(Number),
18 Bool(bool),
19 Ip(IpAddr),
20 Array(Vec<Value<'a>>),
21 Map(BTreeMap<String, Value<'a>>),
22}
23
24impl<'a> Value<'a> {
25 pub(crate) fn into_static(self) -> Value<'static> {
26 match self {
27 Value::None => Value::None,
28 Value::String(s) => Value::String(Cow::Owned(s.into_owned())),
29 Value::Number(n) => Value::Number(n),
30 Value::Bool(b) => Value::Bool(b),
31 Value::Ip(ip) => Value::Ip(ip),
32 Value::Array(arr) => Value::Array(arr.into_iter().map(|v| v.into_static()).collect()),
33 Value::Map(map) => {
34 Value::Map(map.into_iter().map(|(k, v)| (k, v.into_static())).collect())
35 }
36 }
37 }
38
39 pub fn as_str(&self) -> Option<&str> {
41 match self {
42 Value::String(s) => Some(s),
43 _ => None,
44 }
45 }
46
47 pub fn as_i64(&self) -> Option<i64> {
49 match self {
50 Value::Number(n) => n.as_i64(),
51 _ => None,
52 }
53 }
54
55 pub fn as_f64(&self) -> Option<f64> {
57 match self {
58 Value::Number(n) => n.as_f64(),
59 _ => None,
60 }
61 }
62
63 pub fn as_bool(&self) -> Option<bool> {
65 match self {
66 Value::Bool(b) => Some(*b),
67 _ => None,
68 }
69 }
70
71 pub fn as_ip(&self) -> Option<IpAddr> {
73 match self {
74 Value::Ip(ip) => Some(*ip),
75 _ => None,
76 }
77 }
78
79 pub fn to_ip(&self) -> Result<IpAddr, AddrParseError> {
81 match self {
82 Value::String(s) => IpAddr::from_str(s),
83 Value::Ip(ip) => Ok(*ip),
84 _ => IpAddr::from_str(""), }
86 }
87
88 pub fn as_array(&self) -> Option<&Vec<Value<'a>>> {
90 match self {
91 Value::Array(arr) => Some(arr),
92 _ => None,
93 }
94 }
95
96 pub fn as_array_mut(&mut self) -> Option<&mut Vec<Value<'a>>> {
98 match self {
99 Value::Array(arr) => Some(arr),
100 _ => None,
101 }
102 }
103
104 pub fn as_map(&self) -> Option<&BTreeMap<String, Value<'a>>> {
106 match self {
107 Value::Map(map) => Some(map),
108 _ => None,
109 }
110 }
111
112 pub fn as_map_mut(&mut self) -> Option<&mut BTreeMap<String, Value<'a>>> {
114 match self {
115 Value::Map(map) => Some(map),
116 _ => None,
117 }
118 }
119}
120
121impl PartialOrd for Value<'_> {
122 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
123 match (self, other) {
124 (Value::None, Value::None) => Some(Ordering::Equal),
125 (Value::String(s), Value::String(t)) => s.partial_cmp(t),
126 (Value::Number(i), Value::Number(j)) => {
127 if let (Some(i), Some(j)) = (i.as_i64(), j.as_i64()) {
128 i.partial_cmp(&j)
129 } else if let (Some(i), Some(j)) = (i.as_f64(), j.as_f64()) {
130 i.partial_cmp(&j)
131 } else {
132 None
133 }
134 }
135 (Value::Bool(i), Value::Bool(j)) => i.partial_cmp(j),
136 (Value::Ip(i), Value::Ip(j)) => i.partial_cmp(j),
137 (Value::Array(i), Value::Array(j)) => i.partial_cmp(j),
138 (Value::Map(i), Value::Map(j)) => i.partial_cmp(j),
139 _ => None,
140 }
141 }
142}
143
144impl From<JsonValue> for Value<'_> {
145 fn from(value: JsonValue) -> Self {
146 match value {
147 JsonValue::Null => Value::None,
148 JsonValue::String(s) => Value::String(Cow::Owned(s)),
149 JsonValue::Number(n) => Value::Number(n),
150 JsonValue::Bool(b) => Value::Bool(b),
151 JsonValue::Array(arr) => {
152 let arr = arr.into_iter().map(|v| v.into()).collect();
153 Value::Array(arr)
154 }
155 JsonValue::Object(obj) => {
156 let map = obj.into_iter().map(|(k, v)| (k, v.into())).collect();
157 Value::Map(map)
158 }
159 }
160 }
161}
162
163impl<'a> From<&'a JsonValue> for Value<'a> {
164 fn from(value: &'a JsonValue) -> Self {
165 match value {
166 JsonValue::Null => Value::None,
167 JsonValue::String(s) => Value::String(Cow::Borrowed(s)),
168 JsonValue::Number(n) => Value::Number(n.clone()),
169 JsonValue::Bool(b) => Value::Bool(*b),
170 JsonValue::Array(arr) => Value::Array(arr.iter().map(|v| v.into()).collect()),
171 JsonValue::Object(obj) => {
172 let map = obj.iter().map(|(k, v)| (k.clone(), v.into())).collect();
173 Value::Map(map)
174 }
175 }
176 }
177}
178
179impl From<Value<'_>> for JsonValue {
180 fn from(value: Value<'_>) -> Self {
181 match value {
182 Value::None => JsonValue::Null,
183 Value::String(s) => JsonValue::String(s.into_owned()),
184 Value::Number(n) => JsonValue::Number(n),
185 Value::Bool(b) => JsonValue::Bool(b),
186 Value::Ip(ip) => JsonValue::String(ip.to_string()),
187 Value::Array(arr) => JsonValue::Array(arr.into_iter().map(|v| v.into()).collect()),
188 Value::Map(map) => {
189 JsonValue::Object(map.into_iter().map(|(k, v)| (k, v.into())).collect())
190 }
191 }
192 }
193}
194
195impl From<String> for Value<'_> {
196 #[inline(always)]
197 fn from(s: String) -> Self {
198 Value::String(Cow::Owned(s))
199 }
200}
201
202impl<'a> From<&'a String> for Value<'a> {
203 #[inline(always)]
204 fn from(s: &'a String) -> Self {
205 Value::String(Cow::Borrowed(s))
206 }
207}
208
209impl<'a> From<&'a str> for Value<'a> {
210 #[inline(always)]
211 fn from(s: &'a str) -> Self {
212 Value::String(Cow::Borrowed(s))
213 }
214}
215
216impl<'a> From<Cow<'a, str>> for Value<'a> {
217 #[inline(always)]
218 fn from(s: Cow<'a, str>) -> Self {
219 Value::String(s)
220 }
221}
222
223macro_rules! impl_from_int {
224 ($($ty:ty),*) => {
225 $(
226 impl From<$ty> for Value<'_> {
227 #[inline(always)]
228 fn from(i: $ty) -> Self {
229 Value::Number(Number::from(i))
230 }
231 }
232 )*
233 };
234}
235
236impl_from_int!(i8, u8, i16, u16, i32, u32, i64, u64, isize, usize);
237
238impl TryFrom<f64> for Value<'_> {
239 type Error = ();
240
241 #[inline(always)]
242 fn try_from(f: f64) -> StdResult<Self, Self::Error> {
243 Ok(Value::Number(Number::from_f64(f).ok_or(())?))
244 }
245}
246
247impl From<bool> for Value<'_> {
248 #[inline(always)]
249 fn from(b: bool) -> Self {
250 Value::Bool(b)
251 }
252}
253
254impl From<IpAddr> for Value<'_> {
255 #[inline(always)]
256 fn from(ip: IpAddr) -> Self {
257 Value::Ip(ip)
258 }
259}
260
261impl<'a, T> From<Option<T>> for Value<'a>
262where
263 T: Into<Value<'a>>,
264{
265 #[inline(always)]
266 fn from(opt: Option<T>) -> Self {
267 match opt {
268 Some(v) => v.into(),
269 None => Value::None,
270 }
271 }
272}
273
274impl<'a, T: Into<Value<'a>>> From<Vec<T>> for Value<'a> {
275 #[inline(always)]
276 fn from(arr: Vec<T>) -> Self {
277 Value::Array(arr.into_iter().map(|v| v.into()).collect())
278 }
279}
280
281impl<'a, T: Into<Value<'a>>> From<BTreeMap<String, T>> for Value<'a> {
282 #[inline(always)]
283 fn from(map: BTreeMap<String, T>) -> Self {
284 Value::Map(map.into_iter().map(|(k, v)| (k, v.into())).collect())
285 }
286}
287
288#[cfg(test)]
289mod tests {
290 use super::*;
291
292 #[test]
293 fn test_value() {
294 assert_eq!(Value::None, Value::None);
296
297 let val = Value::from("true").into_static();
299 assert_eq!(val.as_str(), Some("true"));
300 assert_eq!(val.as_i64(), None);
301 assert_eq!(val.as_f64(), None);
302 assert_eq!(val.as_bool(), None);
303 assert!(val.to_ip().is_err());
304 assert!(Value::from("127.0.0.1").to_ip().is_ok());
305 assert!(Value::from("0") < Value::from("1"));
306
307 let val = Value::from(42).into_static();
309 assert_eq!(val.as_str(), None);
310 assert_eq!(val.as_i64(), Some(42));
311 assert_eq!(val.as_f64(), Some(42.0));
312 assert_eq!(val.as_bool(), None);
313 assert!(val.to_ip().is_err());
314 assert!(Value::from(42) < Value::from(43));
315 assert!(Value::try_from(0.001).unwrap() > Value::from(0));
316
317 let val = Value::from(true).into_static();
319 assert_eq!(val.as_str(), None);
320 assert_eq!(val.as_i64(), None);
321 assert_eq!(val.as_f64(), None);
322 assert_eq!(val.as_bool(), Some(true));
323 assert!(val.to_ip().is_err());
324 assert!(Value::from(false) < Value::from(true));
325
326 let val = Value::from(IpAddr::from_str("127.0.0.1").unwrap()).into_static();
328 assert_eq!(val.as_str(), None);
329 assert_eq!(val.as_i64(), None);
330 assert_eq!(val.as_f64(), None);
331 assert_eq!(val.as_bool(), None);
332 assert_eq!(val.to_ip().unwrap(), "127.0.0.1".parse::<IpAddr>().unwrap());
333 assert!(
334 Value::from("127.0.0.1".parse::<IpAddr>().unwrap())
335 < Value::from("127.0.0.2".parse::<IpAddr>().unwrap())
336 );
337
338 let mut val = Value::from(vec!["a", "b", "c"]).into_static();
340 assert_eq!(val.as_array().unwrap().len(), 3);
341 assert_eq!(val.as_map(), None);
342 if let Some(arr) = val.as_array_mut() {
343 arr.push(Value::from("d"));
344 }
345 assert_eq!(val.as_array().unwrap().len(), 4);
346 assert!(Value::from(vec![1, 2, 3]) < Value::from(vec![1, 2, 4]));
347
348 let mut val = Value::from(BTreeMap::from_iter(vec![
350 ("key1".to_string(), Value::from("value1")),
351 ("key2".to_string(), Value::from(42)),
352 ]))
353 .into_static();
354 assert_eq!(val.as_map().unwrap().len(), 2);
355 assert_eq!(val.as_array(), None);
356 if let Some(m) = val.as_map_mut() {
357 m.insert("key3".to_string(), Value::from(true));
358 }
359 assert_eq!(val.as_map().unwrap().len(), 3);
360 assert!(
361 Value::from(BTreeMap::from_iter(vec![("a".to_string(), Value::from(1))]))
362 < Value::from(BTreeMap::from_iter(vec![("a".to_string(), Value::from(2))]))
363 );
364
365 let json_val: JsonValue = serde_json::json!({
367 "string": "value",
368 "number": 42,
369 "bool": true,
370 "array": [1, 2, 3],
371 "map": { "key": "value" },
372 "null": null
373 });
374 assert_eq!(Value::from(&json_val), Value::from(json_val.clone()));
375 let back_to_json: JsonValue = Value::from(json_val.clone()).into();
376 assert_eq!(back_to_json, json_val);
377 }
378}