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<String> for Value<'_> {
180 #[inline(always)]
181 fn from(s: String) -> Self {
182 Value::String(Cow::Owned(s))
183 }
184}
185
186impl<'a> From<&'a String> for Value<'a> {
187 #[inline(always)]
188 fn from(s: &'a String) -> Self {
189 Value::String(Cow::Borrowed(s))
190 }
191}
192
193impl<'a> From<&'a str> for Value<'a> {
194 #[inline(always)]
195 fn from(s: &'a str) -> Self {
196 Value::String(Cow::Borrowed(s))
197 }
198}
199
200impl<'a> From<Cow<'a, str>> for Value<'a> {
201 #[inline(always)]
202 fn from(s: Cow<'a, str>) -> Self {
203 Value::String(s)
204 }
205}
206
207macro_rules! impl_from_int {
208 ($($ty:ty),*) => {
209 $(
210 impl From<$ty> for Value<'_> {
211 #[inline(always)]
212 fn from(i: $ty) -> Self {
213 Value::Number(Number::from(i))
214 }
215 }
216 )*
217 };
218}
219
220impl_from_int!(i8, u8, i16, u16, i32, u32, i64, u64, isize, usize);
221
222impl TryFrom<f64> for Value<'_> {
223 type Error = ();
224
225 #[inline(always)]
226 fn try_from(f: f64) -> StdResult<Self, Self::Error> {
227 Ok(Value::Number(Number::from_f64(f).ok_or(())?))
228 }
229}
230
231impl From<bool> for Value<'_> {
232 #[inline(always)]
233 fn from(b: bool) -> Self {
234 Value::Bool(b)
235 }
236}
237
238impl From<IpAddr> for Value<'_> {
239 #[inline(always)]
240 fn from(ip: IpAddr) -> Self {
241 Value::Ip(ip)
242 }
243}
244
245impl<'a, T> From<Option<T>> for Value<'a>
246where
247 T: Into<Value<'a>>,
248{
249 #[inline(always)]
250 fn from(opt: Option<T>) -> Self {
251 match opt {
252 Some(v) => v.into(),
253 None => Value::None,
254 }
255 }
256}
257
258impl<'a, T: Into<Value<'a>>> From<Vec<T>> for Value<'a> {
259 #[inline(always)]
260 fn from(arr: Vec<T>) -> Self {
261 Value::Array(arr.into_iter().map(|v| v.into()).collect())
262 }
263}