relay_protocol/
value.rs

1use std::collections::BTreeMap;
2use std::fmt::Debug;
3use std::{fmt, str};
4
5use serde::de::{Deserialize, MapAccess, SeqAccess, Visitor};
6use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
7use uuid::Uuid;
8
9use crate::annotated::Annotated;
10use crate::meta::Meta;
11
12/// Alias for typed arrays.
13pub type Array<T> = Vec<Annotated<T>>;
14
15/// Alias for maps.
16pub type Map<K, T> = BTreeMap<K, T>;
17
18/// Alias for typed objects.
19pub type Object<T> = Map<String, Annotated<T>>;
20
21/// Represents a boxed value.
22#[derive(Debug, Clone, PartialEq)]
23pub enum Value {
24    /// A boolean value.
25    Bool(bool),
26    /// A signed integer value.
27    I64(i64),
28    /// An unsigned integer value.
29    U64(u64),
30    /// A floating point value.
31    F64(f64),
32    /// A string value.
33    String(String),
34    /// An array of annotated values.
35    Array(Array<Value>),
36    /// A mapping of strings to annotated values.
37    Object(Object<Value>),
38}
39
40/// Helper type that renders out a description of the value.
41pub struct ValueDescription<'a>(&'a Value);
42
43impl fmt::Display for ValueDescription<'_> {
44    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45        match *self.0 {
46            Value::Bool(true) => f.pad("true"),
47            Value::Bool(false) => f.pad("false"),
48            Value::I64(val) => write!(f, "integer {val}"),
49            Value::U64(val) => write!(f, "integer {val}"),
50            Value::F64(val) => write!(f, "float {val}"),
51            Value::String(ref val) => f.pad(val),
52            Value::Array(_) => f.pad("an array"),
53            Value::Object(_) => f.pad("an object"),
54        }
55    }
56}
57
58impl Value {
59    /// Returns a formattable that gives a helper description of the value.
60    pub fn describe(&self) -> ValueDescription<'_> {
61        ValueDescription(self)
62    }
63
64    /// Returns the string if this value is a string, otherwise `None`.
65    pub fn as_str(&self) -> Option<&str> {
66        match self {
67            Value::String(string) => Some(string.as_str()),
68            _ => None,
69        }
70    }
71
72    /// Constructs a `Value` from a `serde_json::Value` object.
73    fn from_json(value: serde_json::Value) -> Option<Self> {
74        Some(match value {
75            serde_json::Value::Null => return None,
76            serde_json::Value::Bool(value) => Value::Bool(value),
77            serde_json::Value::Number(num) => {
78                if let Some(val) = num.as_i64() {
79                    Value::I64(val)
80                } else if let Some(val) = num.as_u64() {
81                    Value::U64(val)
82                } else if let Some(val) = num.as_f64() {
83                    Value::F64(val)
84                } else {
85                    // NB: Without the "arbitrary_precision" feature, serde_json's number will
86                    // always be one of the above.
87                    unreachable!()
88                }
89            }
90            serde_json::Value::String(val) => Value::String(val),
91            serde_json::Value::Array(items) => {
92                Value::Array(items.into_iter().map(Annotated::<Value>::from).collect())
93            }
94            serde_json::Value::Object(items) => Value::Object(
95                items
96                    .into_iter()
97                    .map(|(k, v)| (k, Annotated::<Value>::from(v)))
98                    .collect(),
99            ),
100        })
101    }
102}
103
104impl TryFrom<&Value> for String {
105    type Error = ();
106
107    fn try_from(value: &Value) -> Result<Self, Self::Error> {
108        Ok(match value {
109            Value::Bool(v) => v.to_string(),
110            Value::I64(v) => v.to_string(),
111            Value::U64(v) => v.to_string(),
112            Value::F64(v) => v.to_string(),
113            Value::String(v) => v.to_string(),
114            _ => return Err(()),
115        })
116    }
117}
118
119impl Serialize for Value {
120    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
121    where
122        S: Serializer,
123    {
124        match *self {
125            Value::Bool(val) => serializer.serialize_bool(val),
126            Value::I64(val) => serializer.serialize_i64(val),
127            Value::U64(val) => serializer.serialize_u64(val),
128            Value::F64(val) => serializer.serialize_f64(val),
129            Value::String(ref val) => serializer.serialize_str(val),
130            Value::Array(ref items) => {
131                let mut seq_ser = serializer.serialize_seq(Some(items.len()))?;
132                for item in items {
133                    match item {
134                        Annotated(Some(val), _) => seq_ser.serialize_element(val)?,
135                        Annotated(None, _) => seq_ser.serialize_element(&())?,
136                    }
137                }
138                seq_ser.end()
139            }
140            Value::Object(ref items) => {
141                let mut map_ser = serializer.serialize_map(Some(items.len()))?;
142                for (key, value) in items {
143                    map_ser.serialize_key(key)?;
144                    match value {
145                        Annotated(Some(val), _) => map_ser.serialize_value(val)?,
146                        Annotated(None, _) => map_ser.serialize_value(&())?,
147                    }
148                }
149                map_ser.end()
150            }
151        }
152    }
153}
154
155impl From<serde_json::Value> for Annotated<Value> {
156    fn from(value: serde_json::Value) -> Annotated<Value> {
157        Annotated::from(Value::from_json(value))
158    }
159}
160
161impl From<Value> for serde_json::Value {
162    fn from(value: Value) -> serde_json::Value {
163        match value {
164            Value::Bool(value) => serde_json::Value::Bool(value),
165            Value::I64(value) => serde_json::Value::Number(value.into()),
166            Value::U64(value) => serde_json::Value::Number(value.into()),
167            Value::F64(value) => serde_json::Number::from_f64(value)
168                .map(serde_json::Value::Number)
169                .unwrap_or(serde_json::Value::Null),
170            Value::String(val) => serde_json::Value::String(val),
171            Value::Array(items) => {
172                serde_json::Value::Array(items.into_iter().map(serde_json::Value::from).collect())
173            }
174            Value::Object(items) => serde_json::Value::Object(
175                items
176                    .into_iter()
177                    .map(|(k, v)| (k, serde_json::Value::from(v)))
178                    .collect(),
179            ),
180        }
181    }
182}
183
184impl From<Annotated<Value>> for serde_json::Value {
185    fn from(value: Annotated<Value>) -> serde_json::Value {
186        value
187            .0
188            .map(serde_json::Value::from)
189            .unwrap_or(serde_json::Value::Null)
190    }
191}
192
193impl From<bool> for Value {
194    fn from(value: bool) -> Self {
195        Value::Bool(value)
196    }
197}
198
199impl From<i64> for Value {
200    fn from(value: i64) -> Self {
201        Value::I64(value)
202    }
203}
204
205impl From<u64> for Value {
206    fn from(value: u64) -> Self {
207        Value::U64(value)
208    }
209}
210
211impl From<f64> for Value {
212    fn from(value: f64) -> Self {
213        Value::F64(value)
214    }
215}
216
217impl<'a> From<&'a str> for Value {
218    fn from(value: &'a str) -> Self {
219        Value::String(value.to_string())
220    }
221}
222
223impl From<String> for Value {
224    fn from(value: String) -> Self {
225        Value::String(value)
226    }
227}
228
229impl From<Array<Value>> for Value {
230    fn from(value: Array<Value>) -> Self {
231        Value::Array(value)
232    }
233}
234
235impl From<Object<Value>> for Value {
236    fn from(value: Object<Value>) -> Self {
237        Value::Object(value)
238    }
239}
240
241impl<'de> Deserialize<'de> for Value {
242    #[inline]
243    fn deserialize<D>(deserializer: D) -> Result<Value, D::Error>
244    where
245        D: serde::Deserializer<'de>,
246    {
247        struct ValueVisitor;
248
249        impl<'de> Visitor<'de> for ValueVisitor {
250            type Value = Value;
251
252            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
253                formatter.write_str("any valid JSON value")
254            }
255
256            #[inline]
257            fn visit_bool<E>(self, value: bool) -> Result<Value, E> {
258                Ok(Value::Bool(value))
259            }
260
261            #[inline]
262            fn visit_i64<E>(self, value: i64) -> Result<Value, E> {
263                Ok(Value::I64(value))
264            }
265
266            #[inline]
267            fn visit_u64<E>(self, value: u64) -> Result<Value, E> {
268                Ok(value
269                    .try_into()
270                    .map(Value::I64)
271                    .unwrap_or(Value::U64(value)))
272            }
273
274            #[inline]
275            fn visit_f64<E>(self, value: f64) -> Result<Value, E> {
276                Ok(Value::F64(value))
277            }
278
279            #[inline]
280            fn visit_str<E>(self, value: &str) -> Result<Value, E>
281            where
282                E: serde::de::Error,
283            {
284                self.visit_string(String::from(value))
285            }
286
287            #[inline]
288            fn visit_string<E>(self, value: String) -> Result<Value, E> {
289                Ok(Value::String(value))
290            }
291
292            #[inline]
293            fn visit_some<D>(self, deserializer: D) -> Result<Value, D::Error>
294            where
295                D: serde::Deserializer<'de>,
296            {
297                Deserialize::deserialize(deserializer)
298            }
299
300            #[inline]
301            fn visit_seq<V>(self, mut visitor: V) -> Result<Value, V::Error>
302            where
303                V: SeqAccess<'de>,
304            {
305                let mut vec = Vec::new();
306                while let Some(elem) = visitor.next_element()? {
307                    vec.push(Annotated(elem, Meta::default()));
308                }
309                Ok(Value::Array(vec))
310            }
311
312            fn visit_map<V>(self, mut visitor: V) -> Result<Value, V::Error>
313            where
314                V: MapAccess<'de>,
315            {
316                let mut values = Map::new();
317                while let Some((key, value)) = visitor.next_entry()? {
318                    values.insert(key, Annotated(value, Meta::default()));
319                }
320                Ok(Value::Object(values))
321            }
322        }
323
324        deserializer.deserialize_any(ValueVisitor)
325    }
326}
327
328/// Convert `T` into a `Value`.
329pub fn to_value<T>(value: &T) -> Result<Option<Value>, serde_json::Error>
330where
331    T: Serialize,
332{
333    serde_json::to_value(value).map(Value::from_json)
334}
335
336/// Borrowed version of [`Array`].
337#[derive(Debug, Clone, Copy)]
338pub struct Arr<'a> {
339    _phantom: std::marker::PhantomData<&'a ()>,
340}
341
342/// Borrowed version of [`Object`].
343#[derive(Debug, Clone, Copy)]
344pub struct Obj<'a> {
345    _phantom: std::marker::PhantomData<&'a ()>,
346}
347
348/// Borrowed version of [`Value`].
349#[derive(Debug, Clone, Copy)]
350pub enum Val<'a> {
351    /// A boolean value.
352    Bool(bool),
353    /// A signed integer value.
354    I64(i64),
355    /// An unsigned integer value.
356    U64(u64),
357    /// A floating point value.
358    F64(f64),
359    /// A string value.
360    String(&'a str),
361    /// A UUID.
362    Uuid(Uuid),
363    /// An array of annotated values.
364    Array(Arr<'a>),
365    /// A mapping of strings to annotated values.
366    Object(Obj<'a>),
367}
368
369impl<'a> Val<'a> {
370    /// Returns the value if it is a boolean, otherwise `None`.
371    pub fn as_bool(&self) -> Option<bool> {
372        match self {
373            Self::Bool(value) => Some(*value),
374            _ => None,
375        }
376    }
377
378    /// Represents the value as `f64` if possible. Returns `None` otherwise.
379    pub fn as_i64(&self) -> Option<i64> {
380        match self {
381            Self::I64(value) => Some(*value),
382            Self::U64(value) => (*value).try_into().ok(),
383            _ => None,
384        }
385    }
386
387    /// Represents the value as `f64` if possible. Returns `None` otherwise.
388    pub fn as_u64(&self) -> Option<u64> {
389        match self {
390            Self::I64(value) => (*value).try_into().ok(),
391            Self::U64(value) => Some(*value),
392            _ => None,
393        }
394    }
395
396    /// Represents the value as `f64` if possible. Returns `None` otherwise.
397    pub fn as_f64(&self) -> Option<f64> {
398        match self {
399            Self::I64(value) => Some(*value as f64),
400            Self::U64(value) => Some(*value as f64),
401            Self::F64(value) => Some(*value),
402            _ => None,
403        }
404    }
405
406    /// Returns the string if this value is a string, otherwise `None`.
407    pub fn as_str(&self) -> Option<&'a str> {
408        match self {
409            Self::String(value) => Some(value),
410
411            _ => None,
412        }
413    }
414
415    /// Returns the UUID if this value is a UUID, otherwise `None`.
416    pub fn as_uuid(&self) -> Option<Uuid> {
417        match self {
418            Self::Uuid(value) => Some(*value),
419            _ => None,
420        }
421    }
422}
423
424impl From<bool> for Val<'_> {
425    fn from(value: bool) -> Self {
426        Self::Bool(value)
427    }
428}
429
430impl From<i64> for Val<'_> {
431    fn from(value: i64) -> Self {
432        Self::I64(value)
433    }
434}
435
436impl From<u64> for Val<'_> {
437    fn from(value: u64) -> Self {
438        Self::U64(value)
439    }
440}
441
442impl From<f64> for Val<'_> {
443    fn from(value: f64) -> Self {
444        Self::F64(value)
445    }
446}
447
448impl<'a> From<&'a str> for Val<'a> {
449    fn from(value: &'a str) -> Self {
450        Self::String(value)
451    }
452}
453
454impl From<Uuid> for Val<'_> {
455    fn from(value: Uuid) -> Self {
456        Self::Uuid(value)
457    }
458}
459
460impl<'a, T> From<&'a T> for Val<'a>
461where
462    Val<'a>: From<T>,
463    T: Copy,
464{
465    fn from(value: &'a T) -> Self {
466        (*value).into()
467    }
468}
469
470impl<'a> From<&'a Value> for Val<'a> {
471    fn from(value: &'a Value) -> Self {
472        match value {
473            Value::Bool(value) => Self::Bool(*value),
474            Value::I64(value) => Self::I64(*value),
475            Value::U64(value) => Self::U64(*value),
476            Value::F64(value) => Self::F64(*value),
477            Value::String(value) => Self::String(value),
478            Value::Array(_) => Self::Array(Arr {
479                _phantom: Default::default(),
480            }),
481            Value::Object(_) => Self::Object(Obj {
482                _phantom: Default::default(),
483            }),
484        }
485    }
486}
487
488impl PartialEq for Val<'_> {
489    fn eq(&self, other: &Self) -> bool {
490        match (self, other) {
491            (Self::Bool(l0), Self::Bool(r0)) => l0 == r0,
492            (Self::I64(l0), Self::I64(r0)) => l0 == r0,
493            (Self::I64(l0), Self::U64(r0)) => Ok(*l0) == (*r0).try_into(),
494            (Self::U64(l0), Self::U64(r0)) => l0 == r0,
495            (Self::U64(l0), Self::I64(r0)) => Ok(*l0) == (*r0).try_into(),
496            (Self::F64(l0), Self::F64(r0)) => l0 == r0,
497            (Self::String(l0), Self::String(r0)) => l0 == r0,
498            (Self::Uuid(l0), Self::Uuid(r0)) => l0 == r0,
499            (Self::Array(_), Self::Array(_)) => false,
500            (Self::Object(_), Self::Object(_)) => false,
501            _ => false,
502        }
503    }
504}
505
506#[cfg(test)]
507mod tests {
508    use super::*;
509
510    #[test]
511    fn test_unsigned_signed() {
512        let v: Value = serde_json::from_str("9223372036854775816").unwrap();
513        assert_eq!(v, Value::U64(9223372036854775816));
514
515        let v: Value = serde_json::from_str("123").unwrap();
516        assert_eq!(v, Value::I64(123));
517    }
518}