1use crate::index::Index;
2use alloc::string::String;
3use alloc::vec::Vec;
4use core::fmt::{self, Debug};
5use core::mem;
6use core::str;
7use std::collections::BTreeMap;
8use std::f32;
9
10#[derive(Clone)]
11pub enum Value {
12 Null,
13
14 Bool(bool),
15
16 Int(i64),
17 UInt(u64),
18 Float(f64),
19
20 String(String),
21
22 Array(Vec<Value>),
23
24 Map(BTreeMap<String, Value>),
25}
26impl Eq for Value {}
27
28impl PartialEq for Value {
29 fn eq(&self, other: &Self) -> bool {
30 match (self, other) {
31 (Self::Null, Self::Null) => true,
32 (Self::Bool(f1), Self::Bool(f2)) => f1 == f2,
33 (Self::Int(f1), Self::Int(f2)) => f1 == f2,
34 (Self::UInt(f1), Self::UInt(f2)) => f1 == f2,
35 (Self::Float(f1), Self::Float(f2)) => f1.to_string() == f2.to_string(),
36 (Self::String(f1), Self::String(f2)) => f1 == f2,
37 (Self::Array(f1), Self::Array(f2)) => f1 == f2,
38 (Self::Map(f1), Self::Map(f2)) => f1 == f2,
39 _ => false,
40 }
41 }
42}
43
44impl Debug for Value {
45 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
46 match self {
47 Value::Null => formatter.write_str("Null"),
48 Value::Bool(boolean) => write!(formatter, "Bool({})", boolean),
49 Value::String(string) => write!(formatter, "String({:?})", string),
50 Value::Array(vec) => {
51 formatter.write_str("Array ")?;
52 Debug::fmt(vec, formatter)
53 }
54 Value::Map(map) => {
55 formatter.write_str("Map ")?;
56 Debug::fmt(map, formatter)
57 }
58 Value::Int(i) => Debug::fmt(i, formatter),
59 Value::UInt(u) => Debug::fmt(u, formatter),
60 Value::Float(f) => Debug::fmt(f, formatter),
61 }
62 }
63}
64
65impl From<&str> for Value {
66 fn from(s: &str) -> Self {
67 Value::String(s.to_string())
68 }
69}
70impl From<bool> for Value {
71 fn from(b: bool) -> Self {
72 Value::Bool(b)
73 }
74}
75impl From<BTreeMap<String, Value>> for Value {
76 fn from(t: BTreeMap<String, Value>) -> Self {
77 Value::Map(t)
78 }
79}
80
81fn parse_index(s: &str) -> Option<usize> {
82 if s.starts_with('+') || (s.starts_with('0') && s.len() != 1) {
83 return None;
84 }
85 s.parse().ok()
86}
87
88impl Value {
89 pub fn get<I: Index>(&self, index: I) -> Option<&Value> {
90 index.index_into(self)
91 }
92
93 pub fn get_mut<I: Index>(&mut self, index: I) -> Option<&mut Value> {
94 index.index_into_mut(self)
95 }
96
97 pub fn is_object(&self) -> bool {
98 self.as_object().is_some()
99 }
100
101 pub fn as_object(&self) -> Option<&BTreeMap<String, Value>> {
102 match self {
103 Value::Map(map) => Some(map),
104 _ => None,
105 }
106 }
107
108 pub fn as_object_mut(&mut self) -> Option<&mut BTreeMap<String, Value>> {
109 match self {
110 Value::Map(map) => Some(map),
111 _ => None,
112 }
113 }
114
115 pub fn is_array(&self) -> bool {
116 self.as_array().is_some()
117 }
118
119 pub fn as_array(&self) -> Option<&Vec<Value>> {
120 match self {
121 Value::Array(array) => Some(array),
122 _ => None,
123 }
124 }
125
126 pub fn as_array_mut(&mut self) -> Option<&mut Vec<Value>> {
127 match self {
128 Value::Array(list) => Some(list),
129 _ => None,
130 }
131 }
132
133 pub fn is_string(&self) -> bool {
134 self.as_str().is_some()
135 }
136
137 pub fn as_str(&self) -> Option<&str> {
138 match self {
139 Value::String(s) => Some(s),
140 _ => None,
141 }
142 }
143
144 pub fn is_number(&self) -> bool {
145 match *self {
146 Value::Int(_) => true,
147 Value::UInt(_) => true,
148 Value::Float(_) => true,
149 _ => false,
150 }
151 }
152
153 pub fn is_i64(&self) -> bool {
154 match self {
155 Value::Int(_) => true,
156 _ => false,
157 }
158 }
159
160 pub fn is_u64(&self) -> bool {
161 match self {
162 Value::UInt(_) => true,
163 _ => false,
164 }
165 }
166
167 pub fn is_f64(&self) -> bool {
168 match self {
169 Value::Float(_) => true,
170 _ => false,
171 }
172 }
173
174 pub fn as_i64(&self) -> Option<i64> {
175 match self {
176 Value::Int(n) => Some(*n),
177 Value::UInt(n) => {
178 if n <= &(i64::MAX as u64) {
179 Some(*n as i64)
180 } else {
181 None
182 }
183 }
184 Value::Float(n) => None,
185 _ => None,
186 }
187 }
188
189 pub fn as_u64(&self) -> Option<u64> {
190 match self {
191 Value::Int(n) => {
192 if n.is_negative() {
193 None
194 } else {
195 Some(*n as u64)
196 }
197 }
198 Value::UInt(n) => Some(*n),
199 Value::Float(n) => None,
200 _ => None,
201 }
202 }
203
204 pub fn as_f64(&self) -> Option<f64> {
205 match self {
206 Value::Int(n) => Some(*n as f64),
207 Value::UInt(n) => Some(*n as f64),
208 Value::Float(n) => Some(*n),
209 _ => None,
210 }
211 }
212
213 pub fn is_boolean(&self) -> bool {
214 self.as_bool().is_some()
215 }
216
217 pub fn as_bool(&self) -> Option<bool> {
218 match *self {
219 Value::Bool(b) => Some(b),
220 _ => None,
221 }
222 }
223
224 pub fn is_null(&self) -> bool {
225 self.as_null().is_some()
226 }
227
228 pub fn as_null(&self) -> Option<()> {
245 match *self {
246 Value::Null => Some(()),
247 _ => None,
248 }
249 }
250 pub fn pointer(&self, pointer: &str) -> Option<&Value> {
279 if pointer.is_empty() {
280 return Some(self);
281 }
282 if !pointer.starts_with('/') {
283 return None;
284 }
285 pointer
286 .split('/')
287 .skip(1)
288 .map(|x| x.replace("~1", "/").replace("~0", "~"))
289 .try_fold(self, |target, token| match target {
290 Value::Map(map) => map.get(&token),
291 Value::Array(list) => parse_index(&token).and_then(|x| list.get(x)),
292 _ => None,
293 })
294 }
295 pub fn pointer_mut(&mut self, pointer: &str) -> Option<&mut Value> {
332 if pointer.is_empty() {
333 return Some(self);
334 }
335 if !pointer.starts_with('/') {
336 return None;
337 }
338 pointer
339 .split('/')
340 .skip(1)
341 .map(|x| x.replace("~1", "/").replace("~0", "~"))
342 .try_fold(self, |target, token| match target {
343 Value::Map(map) => map.get_mut(&token),
344 Value::Array(list) => parse_index(&token).and_then(move |x| list.get_mut(x)),
345 _ => None,
346 })
347 }
348
349 pub fn take(&mut self) -> Value {
350 mem::replace(self, Value::Null)
351 }
352}
353
354impl Default for Value {
355 fn default() -> Value {
356 Value::Null
357 }
358}
359
360#[cfg(test)]
361pub mod tests {
362 use crate::value::Value;
363 use std::collections::BTreeMap;
364
365 #[test]
366 fn confirm_values() {
367 let mut v = Value::Int(9);
368 assert!(v.is_i64());
369 assert!(!v.is_f64());
370 assert!(!v.is_u64());
371 let mut v = Value::UInt(9);
372 assert!(v.is_u64());
373 assert!(!v.is_i64());
374 assert!(!v.is_f64());
375 let mut v = Value::Float(9.0);
376 assert!(!v.is_u64());
377 assert!(!v.is_i64());
378 assert!(v.is_f64());
379 v = Value::Array(Vec::new());
380 assert!(v.is_array());
381 v = Value::Bool(false);
382 assert!(v.is_boolean());
383 v = Value::Null;
384 assert!(v.is_null());
385 v = Value::String("".to_string());
386 assert!(v.is_string());
387 }
388
389 #[test]
390 fn pointer_mut_test() {
391 let mut tree = BTreeMap::new();
392 tree.insert("x".to_string(), Value::Float(1.0));
393 tree.insert("y".to_string(), Value::Float(2.0));
394 let mut value: Value = Value::Map(tree);
395
396 assert_eq!(value.pointer("/x"), Some(&Value::Float(1.0)));
398 *value.pointer_mut("/x").unwrap() = Value::Float(1.5);
400 assert_eq!(value.pointer("/x"), Some(&Value::Float(1.5)));
402 value.pointer_mut("/x").map(|v| *v = Value::Float(1.5));
404
405 let old_x = value.pointer_mut("/x").map(Value::take).unwrap();
407 assert_eq!(old_x, Value::Float(1.5));
408 assert_eq!(value.pointer("/x").unwrap(), &Value::Null);
409 }
410}