1#[cfg(feature = "alloc")]
9use alloc::{collections::BTreeMap, string::String, vec::Vec};
10
11use smol_str::SmolStr;
12
13#[derive(Debug, Clone, PartialEq)]
19#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
20#[cfg_attr(feature = "serde", serde(untagged))]
21pub enum Value {
22 Null,
24 Bool(bool),
26 Int(i64),
28 Float(f64),
30 Str(SmolStr),
32 #[cfg(feature = "alloc")]
35 Array(Vec<Value>),
36 #[cfg(feature = "alloc")]
38 Object(BTreeMap<String, Value>),
39}
40
41impl Value {
42 pub const fn is_null(&self) -> bool {
44 matches!(self, Value::Null)
45 }
46
47 pub fn as_str(&self) -> Option<&str> {
49 if let Value::Str(s) = self {
50 Some(s.as_str())
51 } else {
52 None
53 }
54 }
55
56 pub const fn as_int(&self) -> Option<i64> {
58 if let Value::Int(v) = *self {
59 Some(v)
60 } else {
61 None
62 }
63 }
64
65 pub fn as_float(&self) -> Option<f64> {
68 match *self {
69 Value::Float(v) => Some(v),
70 Value::Int(v) => Some(v as f64),
71 _ => None,
72 }
73 }
74}
75
76impl From<bool> for Value {
77 fn from(v: bool) -> Self {
78 Value::Bool(v)
79 }
80}
81impl From<i32> for Value {
82 fn from(v: i32) -> Self {
83 Value::Int(v as i64)
84 }
85}
86impl From<i64> for Value {
87 fn from(v: i64) -> Self {
88 Value::Int(v)
89 }
90}
91impl From<u16> for Value {
92 fn from(v: u16) -> Self {
93 Value::Int(v as i64)
94 }
95}
96impl From<u32> for Value {
97 fn from(v: u32) -> Self {
98 Value::Int(v as i64)
99 }
100}
101impl From<f32> for Value {
102 fn from(v: f32) -> Self {
103 Value::Float(v as f64)
104 }
105}
106impl From<f64> for Value {
107 fn from(v: f64) -> Self {
108 Value::Float(v)
109 }
110}
111impl From<&str> for Value {
112 fn from(v: &str) -> Self {
113 Value::Str(SmolStr::new(v))
114 }
115}
116impl From<SmolStr> for Value {
117 fn from(v: SmolStr) -> Self {
118 Value::Str(v)
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125
126 #[test]
127 fn coercions_round_trip() {
128 assert_eq!(Value::from(42i32).as_int(), Some(42));
129 assert_eq!(Value::from(2.5f64).as_float(), Some(2.5));
130 assert_eq!(Value::from("hi").as_str(), Some("hi"));
131 assert_eq!(Value::from(7i64).as_float(), Some(7.0));
132 assert!(Value::Null.is_null());
133 }
134}