1 use crate::mapping::Entry;
2 use crate::{mapping, private, Mapping, Value};
3 use std::fmt::{self, Debug};
4 use std::ops;
5
6 /// A type that can be used to index into a `serde_yaml::Value`. See the `get`
7 /// and `get_mut` methods of `Value`.
8 ///
9 /// This trait is sealed and cannot be implemented for types outside of
10 /// `serde_yaml`.
11 pub trait Index: private::Sealed {
12 /// Return None if the key is not already in the sequence or object.
13 #[doc(hidden)]
index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>14 fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>;
15
16 /// Return None if the key is not already in the sequence or object.
17 #[doc(hidden)]
index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value>18 fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value>;
19
20 /// Panic if sequence index out of bounds. If key is not already in the object,
21 /// insert it with a value of null. Panic if Value is a type that cannot be
22 /// indexed into, except if Value is null then it can be treated as an empty
23 /// object.
24 #[doc(hidden)]
index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value25 fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value;
26 }
27
28 impl Index for usize {
index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>29 fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
30 match v.untag_ref() {
31 Value::Sequence(vec) => vec.get(*self),
32 Value::Mapping(vec) => vec.get(&Value::Number((*self).into())),
33 _ => None,
34 }
35 }
index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value>36 fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
37 match v.untag_mut() {
38 Value::Sequence(vec) => vec.get_mut(*self),
39 Value::Mapping(vec) => vec.get_mut(&Value::Number((*self).into())),
40 _ => None,
41 }
42 }
index_or_insert<'v>(&self, mut v: &'v mut Value) -> &'v mut Value43 fn index_or_insert<'v>(&self, mut v: &'v mut Value) -> &'v mut Value {
44 loop {
45 match v {
46 Value::Sequence(vec) => {
47 let len = vec.len();
48 return vec.get_mut(*self).unwrap_or_else(|| {
49 panic!(
50 "cannot access index {} of YAML sequence of length {}",
51 self, len
52 )
53 });
54 }
55 Value::Mapping(map) => {
56 let n = Value::Number((*self).into());
57 return map.entry(n).or_insert(Value::Null);
58 }
59 Value::Tagged(tagged) => v = &mut tagged.value,
60 _ => panic!("cannot access index {} of YAML {}", self, Type(v)),
61 }
62 }
63 }
64 }
65
index_into_mapping<'v, I>(index: &I, v: &'v Value) -> Option<&'v Value> where I: ?Sized + mapping::Index,66 fn index_into_mapping<'v, I>(index: &I, v: &'v Value) -> Option<&'v Value>
67 where
68 I: ?Sized + mapping::Index,
69 {
70 match v.untag_ref() {
71 Value::Mapping(map) => map.get(index),
72 _ => None,
73 }
74 }
75
index_into_mut_mapping<'v, I>(index: &I, v: &'v mut Value) -> Option<&'v mut Value> where I: ?Sized + mapping::Index,76 fn index_into_mut_mapping<'v, I>(index: &I, v: &'v mut Value) -> Option<&'v mut Value>
77 where
78 I: ?Sized + mapping::Index,
79 {
80 match v.untag_mut() {
81 Value::Mapping(map) => map.get_mut(index),
82 _ => None,
83 }
84 }
85
index_or_insert_mapping<'v, I>(index: &I, mut v: &'v mut Value) -> &'v mut Value where I: ?Sized + mapping::Index + ToOwned + Debug, Value: From<I::Owned>,86 fn index_or_insert_mapping<'v, I>(index: &I, mut v: &'v mut Value) -> &'v mut Value
87 where
88 I: ?Sized + mapping::Index + ToOwned + Debug,
89 Value: From<I::Owned>,
90 {
91 if let Value::Null = *v {
92 *v = Value::Mapping(Mapping::new());
93 return match v {
94 Value::Mapping(map) => match map.entry(index.to_owned().into()) {
95 Entry::Vacant(entry) => entry.insert(Value::Null),
96 Entry::Occupied(_) => unreachable!(),
97 },
98 _ => unreachable!(),
99 };
100 }
101 loop {
102 match v {
103 Value::Mapping(map) => {
104 return map.entry(index.to_owned().into()).or_insert(Value::Null);
105 }
106 Value::Tagged(tagged) => v = &mut tagged.value,
107 _ => panic!("cannot access key {:?} in YAML {}", index, Type(v)),
108 }
109 }
110 }
111
112 impl Index for Value {
index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>113 fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
114 index_into_mapping(self, v)
115 }
index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value>116 fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
117 index_into_mut_mapping(self, v)
118 }
index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value119 fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
120 index_or_insert_mapping(self, v)
121 }
122 }
123
124 impl Index for str {
index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>125 fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
126 index_into_mapping(self, v)
127 }
index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value>128 fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
129 index_into_mut_mapping(self, v)
130 }
index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value131 fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
132 index_or_insert_mapping(self, v)
133 }
134 }
135
136 impl Index for String {
index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>137 fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
138 self.as_str().index_into(v)
139 }
index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value>140 fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
141 self.as_str().index_into_mut(v)
142 }
index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value143 fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
144 self.as_str().index_or_insert(v)
145 }
146 }
147
148 impl<'a, T> Index for &'a T
149 where
150 T: ?Sized + Index,
151 {
index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>152 fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
153 (**self).index_into(v)
154 }
index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value>155 fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
156 (**self).index_into_mut(v)
157 }
index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value158 fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
159 (**self).index_or_insert(v)
160 }
161 }
162
163 /// Used in panic messages.
164 struct Type<'a>(&'a Value);
165
166 impl<'a> fmt::Display for Type<'a> {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result167 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
168 match self.0 {
169 Value::Null => formatter.write_str("null"),
170 Value::Bool(_) => formatter.write_str("boolean"),
171 Value::Number(_) => formatter.write_str("number"),
172 Value::String(_) => formatter.write_str("string"),
173 Value::Sequence(_) => formatter.write_str("sequence"),
174 Value::Mapping(_) => formatter.write_str("mapping"),
175 Value::Tagged(_) => unreachable!(),
176 }
177 }
178 }
179
180 // The usual semantics of Index is to panic on invalid indexing.
181 //
182 // That said, the usual semantics are for things like `Vec` and `BTreeMap` which
183 // have different use cases than Value. If you are working with a Vec, you know
184 // that you are working with a Vec and you can get the len of the Vec and make
185 // sure your indices are within bounds. The Value use cases are more
186 // loosey-goosey. You got some YAML from an endpoint and you want to pull values
187 // out of it. Outside of this Index impl, you already have the option of using
188 // `value.as_sequence()` and working with the Vec directly, or matching on
189 // `Value::Sequence` and getting the Vec directly. The Index impl means you can
190 // skip that and index directly into the thing using a concise syntax. You don't
191 // have to check the type, you don't have to check the len, it is all about what
192 // you expect the Value to look like.
193 //
194 // Basically the use cases that would be well served by panicking here are
195 // better served by using one of the other approaches: `get` and `get_mut`,
196 // `as_sequence`, or match. The value of this impl is that it adds a way of
197 // working with Value that is not well served by the existing approaches:
198 // concise and careless and sometimes that is exactly what you want.
199 impl<I> ops::Index<I> for Value
200 where
201 I: Index,
202 {
203 type Output = Value;
204
205 /// Index into a `serde_yaml::Value` using the syntax `value[0]` or
206 /// `value["k"]`.
207 ///
208 /// Returns `Value::Null` if the type of `self` does not match the type of
209 /// the index, for example if the index is a string and `self` is a sequence
210 /// or a number. Also returns `Value::Null` if the given key does not exist
211 /// in the map or the given index is not within the bounds of the sequence.
212 ///
213 /// For retrieving deeply nested values, you should have a look at the
214 /// `Value::pointer` method.
215 ///
216 /// # Examples
217 ///
218 /// ```
219 /// # use serde_yaml::Value;
220 /// #
221 /// # fn main() -> serde_yaml::Result<()> {
222 /// let data: serde_yaml::Value = serde_yaml::from_str(r#"{ x: { y: [z, zz] } }"#)?;
223 ///
224 /// assert_eq!(data["x"]["y"], serde_yaml::from_str::<Value>(r#"["z", "zz"]"#).unwrap());
225 /// assert_eq!(data["x"]["y"][0], serde_yaml::from_str::<Value>(r#""z""#).unwrap());
226 ///
227 /// assert_eq!(data["a"], serde_yaml::from_str::<Value>(r#"null"#).unwrap()); // returns null for undefined values
228 /// assert_eq!(data["a"]["b"], serde_yaml::from_str::<Value>(r#"null"#).unwrap()); // does not panic
229 /// # Ok(())
230 /// # }
231 /// ```
index(&self, index: I) -> &Value232 fn index(&self, index: I) -> &Value {
233 static NULL: Value = Value::Null;
234 index.index_into(self).unwrap_or(&NULL)
235 }
236 }
237
238 impl<I> ops::IndexMut<I> for Value
239 where
240 I: Index,
241 {
242 /// Write into a `serde_yaml::Value` using the syntax `value[0] = ...` or
243 /// `value["k"] = ...`.
244 ///
245 /// If the index is a number, the value must be a sequence of length bigger
246 /// than the index. Indexing into a value that is not a sequence or a
247 /// sequence that is too small will panic.
248 ///
249 /// If the index is a string, the value must be an object or null which is
250 /// treated like an empty object. If the key is not already present in the
251 /// object, it will be inserted with a value of null. Indexing into a value
252 /// that is neither an object nor null will panic.
253 ///
254 /// # Examples
255 ///
256 /// ```
257 /// # fn main() -> serde_yaml::Result<()> {
258 /// let mut data: serde_yaml::Value = serde_yaml::from_str(r#"{x: 0}"#)?;
259 ///
260 /// // replace an existing key
261 /// data["x"] = serde_yaml::from_str(r#"1"#)?;
262 ///
263 /// // insert a new key
264 /// data["y"] = serde_yaml::from_str(r#"[false, false, false]"#)?;
265 ///
266 /// // replace a value in a sequence
267 /// data["y"][0] = serde_yaml::from_str(r#"true"#)?;
268 ///
269 /// // inserted a deeply nested key
270 /// data["a"]["b"]["c"]["d"] = serde_yaml::from_str(r#"true"#)?;
271 ///
272 /// println!("{:?}", data);
273 /// # Ok(())
274 /// # }
275 /// ```
index_mut(&mut self, index: I) -> &mut Value276 fn index_mut(&mut self, index: I) -> &mut Value {
277 index.index_or_insert(self)
278 }
279 }
280