1use std::collections::HashMap;
2
3#[derive(Debug, Clone, PartialEq)]
4pub enum Value {
5 Null,
6 Bool(bool),
7 Number(Number),
8 String(String),
9 Array(Vec<Value>),
10 Object(HashMap<String, Value>),
11}
12
13#[derive(Debug, Clone, PartialEq)]
14pub enum Number {
15 UnsignedInt(u64),
16 Int(i64),
17 Size(usize),
18 Float(f64),
19}
20
21impl Value {
22 pub fn null() -> Self {
23 Value::Null
24 }
25
26 pub fn is_null(&self) -> bool {
27 matches!(self, Value::Null)
28 }
29
30 pub fn as_bool(&self) -> Option<bool> {
31 match self {
32 Value::Bool(b) => Some(*b),
33 _ => None,
34 }
35 }
36
37 pub fn as_size(&self) -> Option<usize> {
38 match self {
39 Value::Number(Number::Size(i)) => Some(*i),
40 Value::Number(Number::Int(i)) => Some(*i as usize),
41 Value::Number(Number::UnsignedInt(i)) => Some(*i as usize),
42 Value::Number(Number::Float(f)) => Some(*f as usize),
43 _ => None,
44 }
45 }
46
47 pub fn as_u64(&self) -> Option<u64> {
48 match self {
49 Value::Number(Number::Size(i)) => Some(*i as u64),
50 Value::Number(Number::Int(i)) => Some(*i as u64),
51 Value::Number(Number::UnsignedInt(i)) => Some(*i),
52 Value::Number(Number::Float(f)) => Some(*f as u64),
53 _ => None,
54 }
55 }
56
57 pub fn as_i64(&self) -> Option<i64> {
58 match self {
59 Value::Number(Number::Int(i)) => Some(*i),
60 Value::Number(Number::Float(f)) => Some(*f as i64),
61 _ => None,
62 }
63 }
64
65 pub fn as_f64(&self) -> Option<f64> {
66 match self {
67 Value::Number(Number::Float(f)) => Some(*f),
68 Value::Number(Number::Int(i)) => Some(*i as f64),
69 _ => None,
70 }
71 }
72
73 pub fn as_str(&self) -> Option<&str> {
74 match self {
75 Value::String(s) => Some(s),
76 _ => None,
77 }
78 }
79
80 pub fn as_array(&self) -> Option<&Vec<Value>> {
81 match self {
82 Value::Array(arr) => Some(arr),
83 _ => None,
84 }
85 }
86
87 pub fn as_array_mut(&mut self) -> Option<&mut Vec<Value>> {
88 match self {
89 Value::Array(arr) => Some(arr),
90 _ => None,
91 }
92 }
93
94 pub fn as_object(&self) -> Option<&HashMap<String, Value>> {
95 match self {
96 Value::Object(obj) => Some(obj),
97 _ => None,
98 }
99 }
100
101 pub fn as_object_mut(&mut self) -> Option<&mut HashMap<String, Value>> {
102 match self {
103 Value::Object(obj) => Some(obj),
104 _ => None,
105 }
106 }
107
108 pub fn get(&self, key: &str) -> Option<&Value> {
109 self.as_object()?.get(key)
110 }
111
112 pub fn get_mut(&mut self, key: &str) -> Option<&mut Value> {
113 self.as_object_mut()?.get_mut(key)
114 }
115
116 pub fn get_index(&self, index: usize) -> Option<&Value> {
117 self.as_array()?.get(index)
118 }
119}
120
121impl From<()> for Value {
122 fn from(_: ()) -> Self {
123 Value::Null
124 }
125}
126
127impl From<bool> for Value {
128 fn from(b: bool) -> Self {
129 Value::Bool(b)
130 }
131}
132
133impl From<usize> for Value {
134 fn from(i: usize) -> Self {
135 Value::Number(Number::Size(i))
136 }
137}
138
139impl From<u64> for Value {
140 fn from(i: u64) -> Self {
141 Value::Number(Number::UnsignedInt(i))
142 }
143}
144
145impl From<i64> for Value {
146 fn from(i: i64) -> Self {
147 Value::Number(Number::Int(i))
148 }
149}
150
151impl From<i32> for Value {
152 fn from(i: i32) -> Self {
153 Value::Number(Number::Int(i as i64))
154 }
155}
156
157impl From<f64> for Value {
158 fn from(f: f64) -> Self {
159 Value::Number(Number::Float(f))
160 }
161}
162
163impl From<f32> for Value {
164 fn from(f: f32) -> Self {
165 Value::Number(Number::Float(f as f64))
166 }
167}
168
169impl From<String> for Value {
170 fn from(s: String) -> Self {
171 Value::String(s)
172 }
173}
174
175impl From<&str> for Value {
176 fn from(s: &str) -> Self {
177 Value::String(s.to_string())
178 }
179}
180
181impl<T: Into<Value>> From<Vec<T>> for Value {
182 fn from(v: Vec<T>) -> Self {
183 Value::Array(v.into_iter().map(Into::into).collect())
184 }
185}
186
187impl<T: Into<Value>> From<HashMap<String, T>> for Value {
188 fn from(m: HashMap<String, T>) -> Self {
189 Value::Object(m.into_iter().map(|(k, v)| (k, v.into())).collect())
190 }
191}
192
193#[cfg(feature = "serde_json")]
195impl From<serde_json::Value> for Value {
196 fn from(v: serde_json::Value) -> Self {
197 match v {
198 serde_json::Value::Null => Value::Null,
199 serde_json::Value::Bool(b) => Value::Bool(b),
200 serde_json::Value::Number(n) => {
201 if let Some(i) = n.as_i64() {
202 Value::Number(Number::Int(i))
203 } else if let Some(f) = n.as_f64() {
204 Value::Number(Number::Float(f))
205 } else {
206 Value::Null
207 }
208 }
209 serde_json::Value::String(s) => Value::String(s),
210 serde_json::Value::Array(arr) => {
211 Value::Array(arr.into_iter().map(Value::from).collect())
212 }
213 serde_json::Value::Object(obj) => {
214 Value::Object(obj.into_iter().map(|(k, v)| (k, Value::from(v))).collect())
215 }
216 }
217 }
218}
219
220#[cfg(feature = "serde_json")]
221impl From<Value> for serde_json::Value {
222 fn from(v: Value) -> Self {
223 match v {
224 Value::Null => serde_json::Value::Null,
225 Value::Bool(b) => serde_json::Value::Bool(b),
226 Value::Number(Number::UnsignedInt(i)) => serde_json::Value::Number(i.into()),
227 Value::Number(Number::Size(i)) => serde_json::Value::Number(i.into()),
228 Value::Number(Number::Int(i)) => serde_json::Value::Number(i.into()),
229 Value::Number(Number::Float(f)) => serde_json::Number::from_f64(f)
230 .map(serde_json::Value::Number)
231 .unwrap_or(serde_json::Value::Null),
232 Value::String(s) => serde_json::Value::String(s),
233 Value::Array(arr) => {
234 serde_json::Value::Array(arr.into_iter().map(serde_json::Value::from).collect())
235 }
236 Value::Object(obj) => serde_json::Value::Object(
237 obj.into_iter()
238 .map(|(k, v)| (k, serde_json::Value::from(v)))
239 .collect(),
240 ),
241 }
242 }
243}