hash_value/
value.rs

1use std::{collections::BTreeMap, fmt::Display, hash::Hash};
2
3use possibly::possibly;
4use serde::de::{Expected, Unexpected};
5
6#[derive(Debug, Clone, PartialEq)]
7pub enum Value {
8    Unsigned(u64),
9    Signed(i64),
10    Float(f64),
11    Object(BTreeMap<String, Value>),
12    String(String),
13    Bool(bool),
14    Array(Vec<Value>),
15    Null,
16}
17
18impl Hash for Value {
19    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
20        match self {
21            Self::Array(arr) => arr.hash(state),
22            Self::Object(obj) => obj.hash(state),
23            Self::Bool(b) => b.hash(state),
24            Self::Float(f) => {
25                if f.is_finite() {
26                    f.to_bits().hash(state);
27                } else {
28                    panic!("non finite floats are not supported for hashing")
29                }
30            }
31            Self::Unsigned(i) => i.hash(state),
32            Self::Signed(i) => i.hash(state),
33            Self::Null => std::mem::discriminant(self).hash(state),
34            Self::String(s) => s.hash(state),
35        }
36    }
37}
38
39impl Default for Value {
40    fn default() -> Self {
41        Self::Null
42    }
43}
44
45impl AsRef<Value> for Value {
46    fn as_ref(&self) -> &Value {
47        self
48    }
49}
50
51impl Value {
52    pub fn string<S: AsRef<str>>(str: S) -> Value {
53        Self::String(str.as_ref().to_owned())
54    }
55
56    pub fn float(f: f64) -> Value {
57        Self::Float(f)
58    }
59
60    pub fn object<S: AsRef<str>, V: Into<Value>, A: IntoIterator<Item = (S, V)>>(
61        mapping: A,
62    ) -> Value {
63        Self::Object(
64            mapping
65                .into_iter()
66                .map(|(k, v)| (k.as_ref().to_owned(), v.into()))
67                .collect(),
68        )
69    }
70
71    pub fn array<V: Into<Value>, A: IntoIterator<Item = V>>(elements: A) -> Value {
72        Self::Array(elements.into_iter().map(V::into).collect())
73    }
74
75    pub fn signed(i: i64) -> Value {
76        Self::Signed(i)
77    }
78
79    pub fn unsigned(i: u64) -> Value {
80        Self::Unsigned(i)
81    }
82
83    pub fn bool(b: bool) -> Value {
84        Self::Bool(b)
85    }
86
87    pub fn as_signed(&self) -> Option<i64> {
88        possibly!(self, Self::Signed(i) => *i)
89    }
90
91    pub fn as_unsigned(&self) -> Option<u64> {
92        possibly!(self, Self::Unsigned(i) => *i)
93    }
94
95    pub fn as_float(&self) -> Option<f64> {
96        possibly!(self, Self::Float(f) => *f)
97    }
98
99    pub fn as_object(&self) -> Option<BTreeMap<&str, &Value>> {
100        possibly!(self, Self::Object(obj) => obj.iter()
101            .map(|(key, value)| (key.as_str(), value))
102            .collect()
103        )
104    }
105
106    pub fn as_mut_object(&mut self) -> Option<BTreeMap<&str, &mut Value>> {
107        possibly!(self, Self::Object(obj) => obj.iter_mut()
108            .map(|(key, value)| (key.as_str(), value))
109            .collect()
110        )
111    }
112
113    pub fn as_vec(&self) -> Option<&[Value]> {
114        possibly!(self, Self::Array(vec) => vec.as_slice())
115    }
116
117    pub fn as_vec_and_then<T, C: FnMut(&Value) -> Option<T>>(&self, mapper: C) -> Option<Vec<T>> {
118        self.as_vec()
119            .and_then(|vec| vec.iter().map(mapper).collect())
120    }
121
122    pub fn as_object_and_then<T, C: Fn(&Value) -> Option<T>>(
123        &self,
124        mapper: C,
125    ) -> Option<BTreeMap<String, T>> {
126        match self {
127            Self::Object(object) => object
128                .iter()
129                .map(|(name, value)| {
130                    mapper(value).map(|mapped_value| (name.to_owned(), mapped_value))
131                })
132                .collect(),
133            _ => None,
134        }
135    }
136
137    pub fn as_mut_vec(&mut self) -> Option<&mut [Value]> {
138        possibly!(self, Self::Array(vec) => vec.as_mut_slice())
139    }
140
141    pub fn as_str(&self) -> Option<&str> {
142        possibly!(self, Self::String(s) => s)
143    }
144
145    pub fn as_bool(&self) -> Option<bool> {
146        match self {
147            Self::Bool(bool) => Some(*bool),
148            _ => None,
149        }
150    }
151
152    pub fn is_null(&self) -> bool {
153        matches!(self, Self::Null)
154    }
155
156    /// Get a value at the specified object path. An object path must have the following format: "name.of.my.key".
157    pub fn at<S: AsRef<str>>(&self, path: S) -> Option<&Self> {
158        if let Self::Object(obj) = self {
159            match path.as_ref().split_once('.') {
160                Some((curr, rest)) => obj.get(curr).and_then(|next| next.at(rest)),
161                None => obj.get(path.as_ref()),
162            }
163        } else {
164            None
165        }
166    }
167
168    /// Overwrite with another [`Value`] object. Overwriting is done recursively when the value is a [`Value::Object`].
169    pub fn overwrite<V: AsRef<Value>>(&mut self, source: V) {
170        match (source.as_ref(), self) {
171            (Value::Object(src), Value::Object(dst)) => {
172                for (key, val) in src {
173                    if let Some(existing) = dst.get_mut(key) {
174                        existing.overwrite(val);
175                    } else {
176                        let _ = dst.insert(key.clone(), val.clone());
177                    }
178                }
179            }
180            (source, target) => {
181                let _ = std::mem::replace(target, source.clone());
182            }
183        }
184    }
185
186    pub(crate) fn invalid_type<E>(&self, exp: &dyn Expected) -> E
187    where
188        E: serde::de::Error,
189    {
190        serde::de::Error::invalid_type(self.unexpected(), exp)
191    }
192
193    pub(crate) fn unexpected(&self) -> Unexpected {
194        match self {
195            Value::Null => Unexpected::Unit,
196            Value::Bool(b) => Unexpected::Bool(*b),
197            Value::Unsigned(i) => Unexpected::Unsigned(*i),
198            Value::Signed(i) => Unexpected::Signed(*i),
199            Value::Float(f) => Unexpected::Float(*f),
200            Value::String(s) => Unexpected::Str(s),
201            Value::Array(_) => Unexpected::Seq,
202            Value::Object(_) => Unexpected::Map,
203        }
204    }
205}
206
207impl From<i8> for Value {
208    fn from(i: i8) -> Self {
209        Self::Signed(i as i64)
210    }
211}
212
213impl From<i16> for Value {
214    fn from(i: i16) -> Self {
215        Self::Signed(i as i64)
216    }
217}
218
219impl From<i32> for Value {
220    fn from(i: i32) -> Self {
221        Self::Signed(i as i64)
222    }
223}
224
225impl From<i64> for Value {
226    fn from(i: i64) -> Self {
227        Self::Signed(i)
228    }
229}
230
231impl From<u8> for Value {
232    fn from(i: u8) -> Self {
233        Self::Unsigned(i as u64)
234    }
235}
236
237impl From<u16> for Value {
238    fn from(i: u16) -> Self {
239        Self::Unsigned(i as u64)
240    }
241}
242
243impl From<u32> for Value {
244    fn from(i: u32) -> Self {
245        Self::Unsigned(i as u64)
246    }
247}
248
249impl From<u64> for Value {
250    fn from(i: u64) -> Self {
251        Self::Unsigned(i)
252    }
253}
254
255impl From<f32> for Value {
256    fn from(f: f32) -> Self {
257        Self::Float(f as f64)
258    }
259}
260
261impl From<f64> for Value {
262    fn from(f: f64) -> Self {
263        Self::Float(f)
264    }
265}
266
267impl From<bool> for Value {
268    fn from(b: bool) -> Self {
269        Self::Bool(b)
270    }
271}
272
273impl From<&str> for Value {
274    fn from(s: &str) -> Self {
275        Self::String(s.to_string())
276    }
277}
278
279impl From<String> for Value {
280    fn from(s: String) -> Self {
281        Self::String(s)
282    }
283}
284
285impl From<Vec<Value>> for Value {
286    fn from(vec: Vec<Value>) -> Self {
287        Self::Array(vec)
288    }
289}
290
291impl From<()> for Value {
292    fn from(_: ()) -> Self {
293        Self::Null
294    }
295}
296
297impl Display for Value {
298    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
299        match self {
300            Self::Bool(bool) => f.write_str(&bool.to_string()),
301            Self::Null => f.write_str("null"),
302            Self::String(str) => write!(
303                f,
304                "\"{}\"",
305                str.replace('\n', "\\n")
306                    .replace('\r', "\\r")
307                    .replace('\t', "\\t")
308            ),
309            Self::Array(arr) => write!(
310                f,
311                "[{}]",
312                arr.iter()
313                    .map(|v| v.to_string())
314                    .collect::<Vec<String>>()
315                    .join(", ")
316            ),
317            Self::Object(obj) => write!(
318                f,
319                "{{{}}}",
320                obj.iter()
321                    .map(|(key, val)| format!("\"{key}\": {}", val))
322                    .collect::<Vec<String>>()
323                    .join(", ")
324            ),
325            Self::Float(i) => f.write_str(i.to_string().as_str()),
326            Self::Unsigned(i) => f.write_str(i.to_string().as_str()),
327            Self::Signed(i) => f.write_str(i.to_string().as_str()),
328        }
329    }
330}