Skip to main content

flexon/value/owned/
mod.rs

1//! Borrowed JSON value representation.
2
3mod string;
4
5use core::{
6    mem::replace,
7    ops::{Index, IndexMut},
8};
9
10use crate::{pointer::JsonPointer, value::misc::define_value};
11
12pub use string::String;
13
14define_value! {
15    /// Represents an owned JSON value.
16    name: Value,
17    string: String,
18    lifetime: '_,
19}
20
21impl Value {
22    /// Returns the value out of self leaving [`Value::Null`] behind.
23    #[inline]
24    pub fn take(&mut self) -> Value {
25        replace(self, Value::Null)
26    }
27
28    /// Returns a reference to the value associated with the given index, `None` otherwise.
29    #[inline]
30    pub fn get<I: JsonPointer>(&self, idx: I) -> Option<&Value> {
31        match self {
32            Value::Array(v) => v.get(idx.as_index()?),
33            Value::Object(v) => v.get(idx.as_key()?),
34            _ => None,
35        }
36    }
37
38    /// Returns a mutable reference to the value associated with the given index, `None` otherwise.
39    #[inline]
40    pub fn get_mut<I: JsonPointer>(&mut self, idx: I) -> Option<&mut Value> {
41        match self {
42            Value::Array(v) => v.get_mut(idx.as_index()?),
43            Value::Object(v) => v.get_mut(idx.as_key()?),
44            _ => None,
45        }
46    }
47
48    /// Returns `()` if it is a null, `None` otherwise.
49    #[inline]
50    pub fn as_null(&self) -> Option<()> {
51        match self {
52            Self::Null => Some(()),
53            _ => None,
54        }
55    }
56
57    /// Returns `bool` if it is a boolean, `None` otherwise.
58    #[inline]
59    pub fn as_bool(&self) -> Option<bool> {
60        match self {
61            Self::Boolean(v) => Some(*v),
62            _ => None,
63        }
64    }
65
66    /// Returns a reference to [`Array`] if it is an array, `None` otherwise.
67    #[inline]
68    pub fn as_array(&self) -> Option<&Array<Self>> {
69        match self {
70            Self::Array(v) => Some(v),
71            _ => None,
72        }
73    }
74
75    /// Returns a mutable reference to [`Array`] if it is an array, `None` otherwise.
76    #[inline]
77    pub fn as_array_mut(&mut self) -> Option<&mut Array<Self>> {
78        match self {
79            Self::Array(v) => Some(v),
80            _ => None,
81        }
82    }
83
84    /// Returns a reference to [`Object`] if it is an object, `None` otherwise.
85    #[inline]
86    pub fn as_object(&self) -> Option<&Object<String, Value>> {
87        match self {
88            Self::Object(v) => Some(v),
89            _ => None,
90        }
91    }
92
93    /// Returns a mutable reference to [`Object`] if it is an object, `None` otherwise.
94    #[inline]
95    pub fn as_object_mut(&mut self) -> Option<&mut Object<String, Value>> {
96        match self {
97            Self::Object(v) => Some(v),
98            _ => None,
99        }
100    }
101
102    /// Returns [`Number`] if it is a number, `None` otherwise.
103    #[inline]
104    pub fn as_number(&self) -> Option<Number> {
105        match *self {
106            Self::Number(v) => Some(v),
107            _ => None,
108        }
109    }
110
111    /// Returns `i64` if it is an integer and negative, `None` otherwise.
112    #[inline]
113    pub fn as_i64(&self) -> Option<i64> {
114        self.as_number()?.as_i64()
115    }
116
117    /// Returns `i64` if it is an integer and positive, `None` otherwise.
118    #[inline]
119    pub fn as_u64(&self) -> Option<u64> {
120        self.as_number()?.as_u64()
121    }
122
123    /// Returns `f64` if it is a floating point number or an integer that is too big, `None` otherwise.
124    #[inline]
125    pub fn as_f64(&self) -> Option<f64> {
126        self.as_number()?.as_f64()
127    }
128
129    /// Returns string slice if it is a string, `None` otherwise.
130    #[inline]
131    pub fn as_str(&self) -> Option<&str> {
132        match self {
133            Self::String(v) => Some(v),
134            _ => None,
135        }
136    }
137
138    /// Returns `true` if it is a string, `false` otherwise.
139    #[inline]
140    pub fn is_str(&self) -> bool {
141        self.as_str().is_some()
142    }
143
144    /// Returns `true` if it is a null, `false` otherwise.
145    #[inline]
146    pub fn is_null(&self) -> bool {
147        self.as_null().is_some()
148    }
149
150    /// Returns `true` if it is a boolean, `false` otherwise.
151    #[inline]
152    pub fn is_bool(&self) -> bool {
153        self.as_bool().is_some()
154    }
155
156    /// Returns `true` if it is an array, `false` otherwise.
157    #[inline]
158    pub fn is_array(&self) -> bool {
159        self.as_array().is_some()
160    }
161
162    /// Returns `true` if it is an object, `false` otherwise.
163    #[inline]
164    pub fn is_object(&self) -> bool {
165        self.as_object().is_some()
166    }
167
168    /// Returns `true` if it is a number, `false` otherwise.
169    #[inline]
170    pub fn is_number(&self) -> bool {
171        self.as_number().is_some()
172    }
173
174    /// Returns `true` if it is an integer and negative, `false` otherwise.
175    #[inline]
176    pub fn is_i64(&self) -> bool {
177        self.as_i64().is_some()
178    }
179
180    /// Returns `true` if it is an integer and positive, `false` otherwise.
181    #[inline]
182    pub fn is_u64(&self) -> bool {
183        self.as_u64().is_some()
184    }
185
186    /// Returns `true` if it is a floating point number or an integer that is too big, `false` otherwise.
187    #[inline]
188    pub fn is_f64(&self) -> bool {
189        self.as_f64().is_some()
190    }
191
192    /// Looks up a value by the given path and returns a reference.
193    ///
194    /// If the path is empty, then the root value is returned.
195    ///
196    /// # Example
197    /// ```
198    /// use flexon::{Value, jsonp};
199    ///
200    /// let val: Value = flexon::parse(r#"{"foo": ["bar", 123]}"#)?;
201    ///
202    /// assert!(val.pointer(jsonp!["foo", 1]).unwrap().is_number());
203    /// assert!(val.pointer([0]).is_none());
204    ///
205    /// # Ok::<_, flexon::Error>(())
206    /// ```
207    pub fn pointer<P>(&self, p: P) -> Option<&Value>
208    where
209        P: IntoIterator,
210        P::Item: JsonPointer,
211    {
212        let mut tmp = self;
213
214        for pointer in p {
215            tmp = match tmp {
216                Value::Object(obj) => obj.get(pointer.as_key()?),
217                Value::Array(arr) => arr.get(pointer.as_index()?),
218                _ => None,
219            }?
220        }
221
222        Some(tmp)
223    }
224
225    /// Looks up a value by the given path and returns a mutable reference.
226    pub fn pointer_mut<P>(&mut self, p: P) -> Option<&mut Value>
227    where
228        P: IntoIterator,
229        P::Item: JsonPointer,
230    {
231        let mut tmp = self;
232
233        for pointer in p {
234            tmp = match tmp {
235                Value::Object(obj) => obj.get_mut(pointer.as_key()?),
236                Value::Array(arr) => arr.get_mut(pointer.as_index()?),
237                _ => None,
238            }?
239        }
240
241        Some(tmp)
242    }
243}
244
245impl Index<usize> for Value {
246    type Output = Value;
247
248    #[inline]
249    fn index(&self, idx: usize) -> &Self::Output {
250        match self.as_array() {
251            Some(v) => match v.get(idx) {
252                Some(v) => v,
253                _ => panic!("given index does not exist in the array"),
254            },
255            _ => panic!("value is not an array"),
256        }
257    }
258}
259
260impl IndexMut<usize> for Value {
261    #[inline]
262    fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
263        match self.as_array_mut() {
264            Some(v) => match v.get_mut(idx) {
265                Some(v) => v,
266                _ => panic!("given index does not exist in the array"),
267            },
268            _ => panic!("value is not an array"),
269        }
270    }
271}
272
273impl Index<&str> for Value {
274    type Output = Value;
275
276    #[inline]
277    fn index(&self, key: &str) -> &Self::Output {
278        match self.as_object() {
279            Some(v) => match v.get(key) {
280                Some(v) => v,
281                _ => panic!("given key does not exist in the object"),
282            },
283            _ => panic!("value is not an object"),
284        }
285    }
286}
287
288impl IndexMut<&str> for Value {
289    #[inline]
290    fn index_mut(&mut self, key: &str) -> &mut Self::Output {
291        match self.as_object_mut() {
292            Some(v) => match v.get_mut(key) {
293                Some(v) => v,
294                _ => panic!("given key does not exist in the object"),
295            },
296            _ => panic!("value is not an object"),
297        }
298    }
299}