]> git.proxmox.com Git - rustc.git/blob - src/vendor/serde_json/src/value/index.rs
New upstream version 1.23.0+dfsg1
[rustc.git] / src / vendor / serde_json / src / value / index.rs
1 // Copyright 2017 Serde Developers
2 //
3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6 // option. This file may not be copied, modified, or distributed
7 // except according to those terms.
8
9 use std::fmt;
10 use std::ops;
11
12 use super::Value;
13 use map::Map;
14
15 /// A type that can be used to index into a `serde_json::Value`.
16 ///
17 /// The [`get`] and [`get_mut`] methods of `Value` accept any type that
18 /// implements `Index`, as does the [square-bracket indexing operator]. This
19 /// trait is implemented for strings which are used as the index into a JSON
20 /// map, and for `usize` which is used as the index into a JSON array.
21 ///
22 /// [`get`]: ../enum.Value.html#method.get
23 /// [`get_mut`]: ../enum.Value.html#method.get_mut
24 /// [square-bracket indexing operator]: ../enum.Value.html#impl-Index%3CI%3E
25 ///
26 /// This trait is sealed and cannot be implemented for types outside of
27 /// `serde_json`.
28 ///
29 /// # Examples
30 ///
31 /// ```rust
32 /// # #[macro_use]
33 /// # extern crate serde_json;
34 /// #
35 /// # fn main() {
36 /// let data = json!({ "inner": [1, 2, 3] });
37 ///
38 /// // Data is a JSON map so it can be indexed with a string.
39 /// let inner = &data["inner"];
40 ///
41 /// // Inner is a JSON array so it can be indexed with an integer.
42 /// let first = &inner[0];
43 ///
44 /// assert_eq!(first, 1);
45 /// # }
46 /// ```
47 pub trait Index: private::Sealed {
48 /// Return None if the key is not already in the array or object.
49 #[doc(hidden)]
50 fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>;
51
52 /// Return None if the key is not already in the array or object.
53 #[doc(hidden)]
54 fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value>;
55
56 /// Panic if array index out of bounds. If key is not already in the object,
57 /// insert it with a value of null. Panic if Value is a type that cannot be
58 /// indexed into, except if Value is null then it can be treated as an empty
59 /// object.
60 #[doc(hidden)]
61 fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value;
62 }
63
64 impl Index for usize {
65 fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
66 match *v {
67 Value::Array(ref vec) => vec.get(*self),
68 _ => None,
69 }
70 }
71 fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
72 match *v {
73 Value::Array(ref mut vec) => vec.get_mut(*self),
74 _ => None,
75 }
76 }
77 fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
78 match *v {
79 Value::Array(ref mut vec) => {
80 let len = vec.len();
81 vec.get_mut(*self)
82 .unwrap_or_else(
83 || {
84 panic!(
85 "cannot access index {} of JSON array of length {}",
86 self,
87 len
88 )
89 },
90 )
91 }
92 _ => panic!("cannot access index {} of JSON {}", self, Type(v)),
93 }
94 }
95 }
96
97 impl Index for str {
98 fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
99 match *v {
100 Value::Object(ref map) => map.get(self),
101 _ => None,
102 }
103 }
104 fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
105 match *v {
106 Value::Object(ref mut map) => map.get_mut(self),
107 _ => None,
108 }
109 }
110 fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
111 if let Value::Null = *v {
112 let mut map = Map::new();
113 map.insert(self.to_owned(), Value::Null);
114 *v = Value::Object(map);
115 }
116 match *v {
117 Value::Object(ref mut map) => {
118 map.entry(self.to_owned()).or_insert(Value::Null)
119 }
120 _ => panic!("cannot access key {:?} in JSON {}", self, Type(v)),
121 }
122 }
123 }
124
125 impl Index for String {
126 fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
127 self[..].index_into(v)
128 }
129 fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
130 self[..].index_into_mut(v)
131 }
132 fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
133 self[..].index_or_insert(v)
134 }
135 }
136
137 impl<'a, T: ?Sized> Index for &'a T
138 where
139 T: Index,
140 {
141 fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
142 (**self).index_into(v)
143 }
144 fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
145 (**self).index_into_mut(v)
146 }
147 fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
148 (**self).index_or_insert(v)
149 }
150 }
151
152 // Prevent users from implementing the Index trait.
153 mod private {
154 pub trait Sealed {}
155 impl Sealed for usize {}
156 impl Sealed for str {}
157 impl Sealed for String {}
158 impl<'a, T: ?Sized> Sealed for &'a T
159 where
160 T: Sealed,
161 {
162 }
163 }
164
165 /// Used in panic messages.
166 struct Type<'a>(&'a Value);
167
168 impl<'a> fmt::Display for Type<'a> {
169 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
170 match *self.0 {
171 Value::Null => formatter.write_str("null"),
172 Value::Bool(_) => formatter.write_str("boolean"),
173 Value::Number(_) => formatter.write_str("number"),
174 Value::String(_) => formatter.write_str("string"),
175 Value::Array(_) => formatter.write_str("array"),
176 Value::Object(_) => formatter.write_str("object"),
177 }
178 }
179 }
180
181 // The usual semantics of Index is to panic on invalid indexing.
182 //
183 // That said, the usual semantics are for things like Vec and BTreeMap which
184 // have different use cases than Value. If you are working with a Vec, you know
185 // that you are working with a Vec and you can get the len of the Vec and make
186 // sure your indices are within bounds. The Value use cases are more
187 // loosey-goosey. You got some JSON from an endpoint and you want to pull values
188 // out of it. Outside of this Index impl, you already have the option of using
189 // value.as_array() and working with the Vec directly, or matching on
190 // Value::Array and getting the Vec directly. The Index impl means you can skip
191 // that and index directly into the thing using a concise syntax. You don't have
192 // to check the type, you don't have to check the len, it is all about what you
193 // expect the Value to look like.
194 //
195 // Basically the use cases that would be well served by panicking here are
196 // better served by using one of the other approaches: get and get_mut,
197 // as_array, or match. The value of this impl is that it adds a way of working
198 // with Value that is not well served by the existing approaches: concise and
199 // careless and sometimes that is exactly what you want.
200 impl<I> ops::Index<I> for Value
201 where
202 I: Index,
203 {
204 type Output = Value;
205
206 /// Index into a `serde_json::Value` using the syntax `value[0]` or
207 /// `value["k"]`.
208 ///
209 /// Returns `Value::Null` if the type of `self` does not match the type of
210 /// the index, for example if the index is a string and `self` is an array
211 /// or a number. Also returns `Value::Null` if the given key does not exist
212 /// in the map or the given index is not within the bounds of the array.
213 ///
214 /// For retrieving deeply nested values, you should have a look at the
215 /// `Value::pointer` method.
216 ///
217 /// # Examples
218 ///
219 /// ```rust
220 /// # #[macro_use]
221 /// # extern crate serde_json;
222 /// #
223 /// # fn main() {
224 /// let data = json!({
225 /// "x": {
226 /// "y": ["z", "zz"]
227 /// }
228 /// });
229 ///
230 /// assert_eq!(data["x"]["y"], json!(["z", "zz"]));
231 /// assert_eq!(data["x"]["y"][0], json!("z"));
232 ///
233 /// assert_eq!(data["a"], json!(null)); // returns null for undefined values
234 /// assert_eq!(data["a"]["b"], json!(null)); // does not panic
235 /// # }
236 /// ```
237 fn index(&self, index: I) -> &Value {
238 static NULL: Value = Value::Null;
239 index.index_into(self).unwrap_or(&NULL)
240 }
241 }
242
243 impl<I> ops::IndexMut<I> for Value
244 where
245 I: Index,
246 {
247 /// Write into a `serde_json::Value` using the syntax `value[0] = ...` or
248 /// `value["k"] = ...`.
249 ///
250 /// If the index is a number, the value must be an array of length bigger
251 /// than the index. Indexing into a value that is not an array or an array
252 /// that is too small will panic.
253 ///
254 /// If the index is a string, the value must be an object or null which is
255 /// treated like an empty object. If the key is not already present in the
256 /// object, it will be inserted with a value of null. Indexing into a value
257 /// that is neither an object nor null will panic.
258 ///
259 /// # Examples
260 ///
261 /// ```rust
262 /// # #[macro_use]
263 /// # extern crate serde_json;
264 /// #
265 /// # fn main() {
266 /// let mut data = json!({ "x": 0 });
267 ///
268 /// // replace an existing key
269 /// data["x"] = json!(1);
270 ///
271 /// // insert a new key
272 /// data["y"] = json!([false, false, false]);
273 ///
274 /// // replace an array value
275 /// data["y"][0] = json!(true);
276 ///
277 /// // inserted a deeply nested key
278 /// data["a"]["b"]["c"]["d"] = json!(true);
279 ///
280 /// println!("{}", data);
281 /// # }
282 /// ```
283 fn index_mut(&mut self, index: I) -> &mut Value {
284 index.index_or_insert(self)
285 }
286 }