1 | use std::iter::FromIterator; |
2 | |
3 | use crate::key::Key; |
4 | use crate::repr::Decor; |
5 | use crate::table::{Iter, IterMut, KeyValuePairs, TableLike}; |
6 | use crate::{InternalString, Item, KeyMut, RawString, Table, Value}; |
7 | |
8 | /// Type representing a TOML inline table, |
9 | /// payload of the `Value::InlineTable` variant |
10 | #[derive (Debug, Default, Clone)] |
11 | pub struct InlineTable { |
12 | // `preamble` represents whitespaces in an empty table |
13 | preamble: RawString, |
14 | // Whether to hide an empty table |
15 | pub(crate) implicit: bool, |
16 | // prefix before `{` and suffix after `}` |
17 | decor: Decor, |
18 | pub(crate) span: Option<std::ops::Range<usize>>, |
19 | // whether this is a proxy for dotted keys |
20 | dotted: bool, |
21 | pub(crate) items: KeyValuePairs, |
22 | } |
23 | |
24 | /// Constructors |
25 | /// |
26 | /// See also `FromIterator` |
27 | impl InlineTable { |
28 | /// Creates an empty table. |
29 | pub fn new() -> Self { |
30 | Default::default() |
31 | } |
32 | |
33 | pub(crate) fn with_pairs(items: KeyValuePairs) -> Self { |
34 | Self { |
35 | items, |
36 | ..Default::default() |
37 | } |
38 | } |
39 | |
40 | /// Convert to a table |
41 | pub fn into_table(self) -> Table { |
42 | let mut t: Table = Table::with_pairs(self.items); |
43 | t.fmt(); |
44 | t |
45 | } |
46 | } |
47 | |
48 | /// Formatting |
49 | impl InlineTable { |
50 | /// Get key/values for values that are visually children of this table |
51 | /// |
52 | /// For example, this will return dotted keys |
53 | pub fn get_values(&self) -> Vec<(Vec<&Key>, &Value)> { |
54 | let mut values = Vec::new(); |
55 | let root = Vec::new(); |
56 | self.append_values(&root, &mut values); |
57 | values |
58 | } |
59 | |
60 | pub(crate) fn append_values<'s>( |
61 | &'s self, |
62 | parent: &[&'s Key], |
63 | values: &mut Vec<(Vec<&'s Key>, &'s Value)>, |
64 | ) { |
65 | for (key, value) in self.items.iter() { |
66 | let mut path = parent.to_vec(); |
67 | path.push(key); |
68 | match value { |
69 | Item::Value(Value::InlineTable(table)) if table.is_dotted() => { |
70 | table.append_values(&path, values); |
71 | } |
72 | Item::Value(value) => { |
73 | values.push((path, value)); |
74 | } |
75 | _ => {} |
76 | } |
77 | } |
78 | } |
79 | |
80 | /// Auto formats the table. |
81 | pub fn fmt(&mut self) { |
82 | decorate_inline_table(self); |
83 | } |
84 | |
85 | /// Sorts the key/value pairs by key. |
86 | pub fn sort_values(&mut self) { |
87 | // Assuming standard tables have their position set and this won't negatively impact them |
88 | self.items.sort_keys(); |
89 | for value in self.items.values_mut() { |
90 | match value { |
91 | Item::Value(Value::InlineTable(table)) if table.is_dotted() => { |
92 | table.sort_values(); |
93 | } |
94 | _ => {} |
95 | } |
96 | } |
97 | } |
98 | |
99 | /// Sort Key/Value Pairs of the table using the using the comparison function `compare`. |
100 | /// |
101 | /// The comparison function receives two key and value pairs to compare (you can sort by keys or |
102 | /// values or their combination as needed). |
103 | pub fn sort_values_by<F>(&mut self, mut compare: F) |
104 | where |
105 | F: FnMut(&Key, &Value, &Key, &Value) -> std::cmp::Ordering, |
106 | { |
107 | self.sort_values_by_internal(&mut compare); |
108 | } |
109 | |
110 | fn sort_values_by_internal<F>(&mut self, compare: &mut F) |
111 | where |
112 | F: FnMut(&Key, &Value, &Key, &Value) -> std::cmp::Ordering, |
113 | { |
114 | let modified_cmp = |
115 | |key1: &Key, val1: &Item, key2: &Key, val2: &Item| -> std::cmp::Ordering { |
116 | match (val1.as_value(), val2.as_value()) { |
117 | (Some(v1), Some(v2)) => compare(key1, v1, key2, v2), |
118 | (Some(_), None) => std::cmp::Ordering::Greater, |
119 | (None, Some(_)) => std::cmp::Ordering::Less, |
120 | (None, None) => std::cmp::Ordering::Equal, |
121 | } |
122 | }; |
123 | |
124 | self.items.sort_by(modified_cmp); |
125 | for value in self.items.values_mut() { |
126 | match value { |
127 | Item::Value(Value::InlineTable(table)) if table.is_dotted() => { |
128 | table.sort_values_by_internal(compare); |
129 | } |
130 | _ => {} |
131 | } |
132 | } |
133 | } |
134 | |
135 | /// If a table has no key/value pairs and implicit, it will not be displayed. |
136 | /// |
137 | /// # Examples |
138 | /// |
139 | /// ```notrust |
140 | /// [target."x86_64/windows.json".dependencies] |
141 | /// ``` |
142 | /// |
143 | /// In the document above, tables `target` and `target."x86_64/windows.json"` are implicit. |
144 | /// |
145 | /// ``` |
146 | /// # #[cfg (feature = "parse" )] { |
147 | /// # #[cfg (feature = "display" )] { |
148 | /// use toml_edit::DocumentMut; |
149 | /// let mut doc = "[a] \n[a.b] \n" .parse::<DocumentMut>().expect("invalid toml" ); |
150 | /// |
151 | /// doc["a" ].as_table_mut().unwrap().set_implicit(true); |
152 | /// assert_eq!(doc.to_string(), "[a.b] \n" ); |
153 | /// # } |
154 | /// # } |
155 | /// ``` |
156 | pub(crate) fn set_implicit(&mut self, implicit: bool) { |
157 | self.implicit = implicit; |
158 | } |
159 | |
160 | /// If a table has no key/value pairs and implicit, it will not be displayed. |
161 | pub(crate) fn is_implicit(&self) -> bool { |
162 | self.implicit |
163 | } |
164 | |
165 | /// Change this table's dotted status |
166 | pub fn set_dotted(&mut self, yes: bool) { |
167 | self.dotted = yes; |
168 | } |
169 | |
170 | /// Check if this is a wrapper for dotted keys, rather than a standard table |
171 | pub fn is_dotted(&self) -> bool { |
172 | self.dotted |
173 | } |
174 | |
175 | /// Returns the surrounding whitespace |
176 | pub fn decor_mut(&mut self) -> &mut Decor { |
177 | &mut self.decor |
178 | } |
179 | |
180 | /// Returns the surrounding whitespace |
181 | pub fn decor(&self) -> &Decor { |
182 | &self.decor |
183 | } |
184 | |
185 | /// Returns an accessor to a key's formatting |
186 | pub fn key(&self, key: &str) -> Option<&'_ Key> { |
187 | self.items.get_full(key).map(|(_, key, _)| key) |
188 | } |
189 | |
190 | /// Returns an accessor to a key's formatting |
191 | pub fn key_mut(&mut self, key: &str) -> Option<KeyMut<'_>> { |
192 | use indexmap::map::MutableKeys; |
193 | self.items |
194 | .get_full_mut2(key) |
195 | .map(|(_, key, _)| key.as_mut()) |
196 | } |
197 | |
198 | /// Returns the decor associated with a given key of the table. |
199 | #[deprecated (since = "0.21.1" , note = "Replaced with `key_mut`" )] |
200 | pub fn key_decor_mut(&mut self, key: &str) -> Option<&mut Decor> { |
201 | #![allow (deprecated)] |
202 | use indexmap::map::MutableKeys; |
203 | self.items |
204 | .get_full_mut2(key) |
205 | .map(|(_, key, _)| key.leaf_decor_mut()) |
206 | } |
207 | |
208 | /// Returns the decor associated with a given key of the table. |
209 | #[deprecated (since = "0.21.1" , note = "Replaced with `key_mut`" )] |
210 | pub fn key_decor(&self, key: &str) -> Option<&Decor> { |
211 | #![allow (deprecated)] |
212 | self.items.get_full(key).map(|(_, key, _)| key.leaf_decor()) |
213 | } |
214 | |
215 | /// Set whitespace after before element |
216 | pub fn set_preamble(&mut self, preamble: impl Into<RawString>) { |
217 | self.preamble = preamble.into(); |
218 | } |
219 | |
220 | /// Whitespace after before element |
221 | pub fn preamble(&self) -> &RawString { |
222 | &self.preamble |
223 | } |
224 | |
225 | /// The location within the original document |
226 | /// |
227 | /// This generally requires an [`ImDocument`][crate::ImDocument]. |
228 | pub fn span(&self) -> Option<std::ops::Range<usize>> { |
229 | self.span.clone() |
230 | } |
231 | |
232 | pub(crate) fn despan(&mut self, input: &str) { |
233 | use indexmap::map::MutableKeys; |
234 | self.span = None; |
235 | self.decor.despan(input); |
236 | self.preamble.despan(input); |
237 | for (key, value) in self.items.iter_mut2() { |
238 | key.despan(input); |
239 | value.despan(input); |
240 | } |
241 | } |
242 | } |
243 | |
244 | impl InlineTable { |
245 | /// Returns an iterator over key/value pairs. |
246 | pub fn iter(&self) -> InlineTableIter<'_> { |
247 | Box::new( |
248 | self.items |
249 | .iter() |
250 | .filter(|(_, value)| !value.is_none()) |
251 | .map(|(key, value)| (key.get(), value.as_value().unwrap())), |
252 | ) |
253 | } |
254 | |
255 | /// Returns an iterator over key/value pairs. |
256 | pub fn iter_mut(&mut self) -> InlineTableIterMut<'_> { |
257 | use indexmap::map::MutableKeys; |
258 | Box::new( |
259 | self.items |
260 | .iter_mut2() |
261 | .filter(|(_, value)| value.is_value()) |
262 | .map(|(key, value)| (key.as_mut(), value.as_value_mut().unwrap())), |
263 | ) |
264 | } |
265 | |
266 | /// Returns the number of key/value pairs. |
267 | pub fn len(&self) -> usize { |
268 | self.iter().count() |
269 | } |
270 | |
271 | /// Returns true if the table is empty. |
272 | pub fn is_empty(&self) -> bool { |
273 | self.len() == 0 |
274 | } |
275 | |
276 | /// Clears the table, removing all key-value pairs. Keeps the allocated memory for reuse. |
277 | pub fn clear(&mut self) { |
278 | self.items.clear(); |
279 | } |
280 | |
281 | /// Gets the given key's corresponding entry in the Table for in-place manipulation. |
282 | pub fn entry(&'_ mut self, key: impl Into<InternalString>) -> InlineEntry<'_> { |
283 | match self.items.entry(key.into().into()) { |
284 | indexmap::map::Entry::Occupied(mut entry) => { |
285 | // Ensure it is a `Value` to simplify `InlineOccupiedEntry`'s code. |
286 | let scratch = std::mem::take(entry.get_mut()); |
287 | let scratch = Item::Value( |
288 | scratch |
289 | .into_value() |
290 | // HACK: `Item::None` is a corner case of a corner case, let's just pick a |
291 | // "safe" value |
292 | .unwrap_or_else(|_| Value::InlineTable(Default::default())), |
293 | ); |
294 | *entry.get_mut() = scratch; |
295 | |
296 | InlineEntry::Occupied(InlineOccupiedEntry { entry }) |
297 | } |
298 | indexmap::map::Entry::Vacant(entry) => InlineEntry::Vacant(InlineVacantEntry { entry }), |
299 | } |
300 | } |
301 | |
302 | /// Gets the given key's corresponding entry in the Table for in-place manipulation. |
303 | pub fn entry_format<'a>(&'a mut self, key: &Key) -> InlineEntry<'a> { |
304 | // Accept a `&Key` to be consistent with `entry` |
305 | match self.items.entry(key.clone()) { |
306 | indexmap::map::Entry::Occupied(mut entry) => { |
307 | // Ensure it is a `Value` to simplify `InlineOccupiedEntry`'s code. |
308 | let scratch = std::mem::take(entry.get_mut()); |
309 | let scratch = Item::Value( |
310 | scratch |
311 | .into_value() |
312 | // HACK: `Item::None` is a corner case of a corner case, let's just pick a |
313 | // "safe" value |
314 | .unwrap_or_else(|_| Value::InlineTable(Default::default())), |
315 | ); |
316 | *entry.get_mut() = scratch; |
317 | |
318 | InlineEntry::Occupied(InlineOccupiedEntry { entry }) |
319 | } |
320 | indexmap::map::Entry::Vacant(entry) => InlineEntry::Vacant(InlineVacantEntry { entry }), |
321 | } |
322 | } |
323 | /// Return an optional reference to the value at the given the key. |
324 | pub fn get(&self, key: &str) -> Option<&Value> { |
325 | self.items.get(key).and_then(|value| value.as_value()) |
326 | } |
327 | |
328 | /// Return an optional mutable reference to the value at the given the key. |
329 | pub fn get_mut(&mut self, key: &str) -> Option<&mut Value> { |
330 | self.items |
331 | .get_mut(key) |
332 | .and_then(|value| value.as_value_mut()) |
333 | } |
334 | |
335 | /// Return references to the key-value pair stored for key, if it is present, else None. |
336 | pub fn get_key_value<'a>(&'a self, key: &str) -> Option<(&'a Key, &'a Item)> { |
337 | self.items.get_full(key).and_then(|(_, key, value)| { |
338 | if !value.is_none() { |
339 | Some((key, value)) |
340 | } else { |
341 | None |
342 | } |
343 | }) |
344 | } |
345 | |
346 | /// Return mutable references to the key-value pair stored for key, if it is present, else None. |
347 | pub fn get_key_value_mut<'a>(&'a mut self, key: &str) -> Option<(KeyMut<'a>, &'a mut Item)> { |
348 | use indexmap::map::MutableKeys; |
349 | self.items.get_full_mut2(key).and_then(|(_, key, value)| { |
350 | if !value.is_none() { |
351 | Some((key.as_mut(), value)) |
352 | } else { |
353 | None |
354 | } |
355 | }) |
356 | } |
357 | |
358 | /// Returns true if the table contains given key. |
359 | pub fn contains_key(&self, key: &str) -> bool { |
360 | if let Some(value) = self.items.get(key) { |
361 | value.is_value() |
362 | } else { |
363 | false |
364 | } |
365 | } |
366 | |
367 | /// Inserts a key/value pair if the table does not contain the key. |
368 | /// Returns a mutable reference to the corresponding value. |
369 | pub fn get_or_insert<V: Into<Value>>( |
370 | &mut self, |
371 | key: impl Into<InternalString>, |
372 | value: V, |
373 | ) -> &mut Value { |
374 | let key = key.into(); |
375 | self.items |
376 | .entry(Key::new(key)) |
377 | .or_insert(Item::Value(value.into())) |
378 | .as_value_mut() |
379 | .expect("non-value type in inline table" ) |
380 | } |
381 | |
382 | /// Inserts a key-value pair into the map. |
383 | pub fn insert(&mut self, key: impl Into<InternalString>, value: Value) -> Option<Value> { |
384 | use indexmap::map::MutableEntryKey; |
385 | let key = Key::new(key); |
386 | let value = Item::Value(value); |
387 | match self.items.entry(key.clone()) { |
388 | indexmap::map::Entry::Occupied(mut entry) => { |
389 | entry.key_mut().fmt(); |
390 | let old = std::mem::replace(entry.get_mut(), value); |
391 | old.into_value().ok() |
392 | } |
393 | indexmap::map::Entry::Vacant(entry) => { |
394 | entry.insert(value); |
395 | None |
396 | } |
397 | } |
398 | } |
399 | |
400 | /// Inserts a key-value pair into the map. |
401 | pub fn insert_formatted(&mut self, key: &Key, value: Value) -> Option<Value> { |
402 | use indexmap::map::MutableEntryKey; |
403 | let value = Item::Value(value); |
404 | match self.items.entry(key.clone()) { |
405 | indexmap::map::Entry::Occupied(mut entry) => { |
406 | *entry.key_mut() = key.clone(); |
407 | let old = std::mem::replace(entry.get_mut(), value); |
408 | old.into_value().ok() |
409 | } |
410 | indexmap::map::Entry::Vacant(entry) => { |
411 | entry.insert(value); |
412 | None |
413 | } |
414 | } |
415 | } |
416 | |
417 | /// Removes an item given the key. |
418 | pub fn remove(&mut self, key: &str) -> Option<Value> { |
419 | self.items |
420 | .shift_remove(key) |
421 | .and_then(|value| value.into_value().ok()) |
422 | } |
423 | |
424 | /// Removes a key from the map, returning the stored key and value if the key was previously in the map. |
425 | pub fn remove_entry(&mut self, key: &str) -> Option<(Key, Value)> { |
426 | self.items |
427 | .shift_remove_entry(key) |
428 | .and_then(|(key, value)| Some((key, value.into_value().ok()?))) |
429 | } |
430 | |
431 | /// Retains only the elements specified by the `keep` predicate. |
432 | /// |
433 | /// In other words, remove all pairs `(key, value)` for which |
434 | /// `keep(&key, &mut value)` returns `false`. |
435 | /// |
436 | /// The elements are visited in iteration order. |
437 | pub fn retain<F>(&mut self, mut keep: F) |
438 | where |
439 | F: FnMut(&str, &mut Value) -> bool, |
440 | { |
441 | self.items.retain(|key, item| { |
442 | item.as_value_mut() |
443 | .map(|value| keep(key, value)) |
444 | .unwrap_or(false) |
445 | }); |
446 | } |
447 | } |
448 | |
449 | #[cfg (feature = "display" )] |
450 | impl std::fmt::Display for InlineTable { |
451 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
452 | crate::encode::encode_table(self, buf:f, input:None, ("" , "" )) |
453 | } |
454 | } |
455 | |
456 | impl<K: Into<Key>, V: Into<Value>> Extend<(K, V)> for InlineTable { |
457 | fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) { |
458 | for (key: K, value: V) in iter { |
459 | let key: Key = key.into(); |
460 | let value: Item = Item::Value(value.into()); |
461 | self.items.insert(key, value); |
462 | } |
463 | } |
464 | } |
465 | |
466 | impl<K: Into<Key>, V: Into<Value>> FromIterator<(K, V)> for InlineTable { |
467 | fn from_iter<I>(iter: I) -> Self |
468 | where |
469 | I: IntoIterator<Item = (K, V)>, |
470 | { |
471 | let mut table: InlineTable = InlineTable::new(); |
472 | table.extend(iter); |
473 | table |
474 | } |
475 | } |
476 | |
477 | impl IntoIterator for InlineTable { |
478 | type Item = (InternalString, Value); |
479 | type IntoIter = InlineTableIntoIter; |
480 | |
481 | fn into_iter(self) -> Self::IntoIter { |
482 | Box::new( |
483 | self.items |
484 | .into_iter() |
485 | .filter(|(_, value: &Item)| value.is_value()) |
486 | .map(|(key: Key, value: Item)| (key.into(), value.into_value().unwrap())), |
487 | ) |
488 | } |
489 | } |
490 | |
491 | impl<'s> IntoIterator for &'s InlineTable { |
492 | type Item = (&'s str, &'s Value); |
493 | type IntoIter = InlineTableIter<'s>; |
494 | |
495 | fn into_iter(self) -> Self::IntoIter { |
496 | self.iter() |
497 | } |
498 | } |
499 | |
500 | fn decorate_inline_table(table: &mut InlineTable) { |
501 | use indexmap::map::MutableKeys; |
502 | for (mut key: KeyMut<'_>, value: &mut Value) in tableimpl Iterator |
503 | .items |
504 | .iter_mut2() |
505 | .filter(|(_, value: &&mut Item)| value.is_value()) |
506 | .map(|(key: &mut Key, value: &mut Item)| (key.as_mut(), value.as_value_mut().unwrap())) |
507 | { |
508 | key.leaf_decor_mut().clear(); |
509 | key.dotted_decor_mut().clear(); |
510 | value.decor_mut().clear(); |
511 | } |
512 | } |
513 | |
514 | /// An owned iterator type over key/value pairs of an inline table. |
515 | pub type InlineTableIntoIter = Box<dyn Iterator<Item = (InternalString, Value)>>; |
516 | /// An iterator type over key/value pairs of an inline table. |
517 | pub type InlineTableIter<'a> = Box<dyn Iterator<Item = (&'a str, &'a Value)> + 'a>; |
518 | /// A mutable iterator type over key/value pairs of an inline table. |
519 | pub type InlineTableIterMut<'a> = Box<dyn Iterator<Item = (KeyMut<'a>, &'a mut Value)> + 'a>; |
520 | |
521 | impl TableLike for InlineTable { |
522 | fn iter(&self) -> Iter<'_> { |
523 | Box::new(self.items.iter().map(|(key, value)| (key.get(), value))) |
524 | } |
525 | fn iter_mut(&mut self) -> IterMut<'_> { |
526 | use indexmap::map::MutableKeys; |
527 | Box::new( |
528 | self.items |
529 | .iter_mut2() |
530 | .map(|(key, value)| (key.as_mut(), value)), |
531 | ) |
532 | } |
533 | fn clear(&mut self) { |
534 | self.clear(); |
535 | } |
536 | fn entry<'a>(&'a mut self, key: &str) -> crate::Entry<'a> { |
537 | // Accept a `&str` rather than an owned type to keep `InternalString`, well, internal |
538 | match self.items.entry(key.into()) { |
539 | indexmap::map::Entry::Occupied(entry) => { |
540 | crate::Entry::Occupied(crate::OccupiedEntry { entry }) |
541 | } |
542 | indexmap::map::Entry::Vacant(entry) => { |
543 | crate::Entry::Vacant(crate::VacantEntry { entry }) |
544 | } |
545 | } |
546 | } |
547 | fn entry_format<'a>(&'a mut self, key: &Key) -> crate::Entry<'a> { |
548 | // Accept a `&Key` to be consistent with `entry` |
549 | match self.items.entry(key.get().into()) { |
550 | indexmap::map::Entry::Occupied(entry) => { |
551 | crate::Entry::Occupied(crate::OccupiedEntry { entry }) |
552 | } |
553 | indexmap::map::Entry::Vacant(entry) => { |
554 | crate::Entry::Vacant(crate::VacantEntry { entry }) |
555 | } |
556 | } |
557 | } |
558 | fn get<'s>(&'s self, key: &str) -> Option<&'s Item> { |
559 | self.items.get(key) |
560 | } |
561 | fn get_mut<'s>(&'s mut self, key: &str) -> Option<&'s mut Item> { |
562 | self.items.get_mut(key) |
563 | } |
564 | fn get_key_value<'a>(&'a self, key: &str) -> Option<(&'a Key, &'a Item)> { |
565 | self.get_key_value(key) |
566 | } |
567 | fn get_key_value_mut<'a>(&'a mut self, key: &str) -> Option<(KeyMut<'a>, &'a mut Item)> { |
568 | self.get_key_value_mut(key) |
569 | } |
570 | fn contains_key(&self, key: &str) -> bool { |
571 | self.contains_key(key) |
572 | } |
573 | fn insert(&mut self, key: &str, value: Item) -> Option<Item> { |
574 | self.insert(key, value.into_value().unwrap()) |
575 | .map(Item::Value) |
576 | } |
577 | fn remove(&mut self, key: &str) -> Option<Item> { |
578 | self.remove(key).map(Item::Value) |
579 | } |
580 | |
581 | fn get_values(&self) -> Vec<(Vec<&Key>, &Value)> { |
582 | self.get_values() |
583 | } |
584 | fn fmt(&mut self) { |
585 | self.fmt(); |
586 | } |
587 | fn sort_values(&mut self) { |
588 | self.sort_values(); |
589 | } |
590 | fn set_dotted(&mut self, yes: bool) { |
591 | self.set_dotted(yes); |
592 | } |
593 | fn is_dotted(&self) -> bool { |
594 | self.is_dotted() |
595 | } |
596 | |
597 | fn key(&self, key: &str) -> Option<&'_ Key> { |
598 | self.key(key) |
599 | } |
600 | fn key_mut(&mut self, key: &str) -> Option<KeyMut<'_>> { |
601 | self.key_mut(key) |
602 | } |
603 | fn key_decor_mut(&mut self, key: &str) -> Option<&mut Decor> { |
604 | #![allow (deprecated)] |
605 | self.key_decor_mut(key) |
606 | } |
607 | fn key_decor(&self, key: &str) -> Option<&Decor> { |
608 | #![allow (deprecated)] |
609 | self.key_decor(key) |
610 | } |
611 | } |
612 | |
613 | // `{ key1 = value1, ... }` |
614 | pub(crate) const DEFAULT_INLINE_KEY_DECOR: (&str, &str) = (" " , " " ); |
615 | |
616 | /// A view into a single location in a map, which may be vacant or occupied. |
617 | pub enum InlineEntry<'a> { |
618 | /// An occupied Entry. |
619 | Occupied(InlineOccupiedEntry<'a>), |
620 | /// A vacant Entry. |
621 | Vacant(InlineVacantEntry<'a>), |
622 | } |
623 | |
624 | impl<'a> InlineEntry<'a> { |
625 | /// Returns the entry key |
626 | /// |
627 | /// # Examples |
628 | /// |
629 | /// ``` |
630 | /// use toml_edit::Table; |
631 | /// |
632 | /// let mut map = Table::new(); |
633 | /// |
634 | /// assert_eq!("hello" , map.entry("hello" ).key()); |
635 | /// ``` |
636 | pub fn key(&self) -> &str { |
637 | match self { |
638 | InlineEntry::Occupied(e) => e.key(), |
639 | InlineEntry::Vacant(e) => e.key(), |
640 | } |
641 | } |
642 | |
643 | /// Ensures a value is in the entry by inserting the default if empty, and returns |
644 | /// a mutable reference to the value in the entry. |
645 | pub fn or_insert(self, default: Value) -> &'a mut Value { |
646 | match self { |
647 | InlineEntry::Occupied(entry) => entry.into_mut(), |
648 | InlineEntry::Vacant(entry) => entry.insert(default), |
649 | } |
650 | } |
651 | |
652 | /// Ensures a value is in the entry by inserting the result of the default function if empty, |
653 | /// and returns a mutable reference to the value in the entry. |
654 | pub fn or_insert_with<F: FnOnce() -> Value>(self, default: F) -> &'a mut Value { |
655 | match self { |
656 | InlineEntry::Occupied(entry) => entry.into_mut(), |
657 | InlineEntry::Vacant(entry) => entry.insert(default()), |
658 | } |
659 | } |
660 | } |
661 | |
662 | /// A view into a single occupied location in a `IndexMap`. |
663 | pub struct InlineOccupiedEntry<'a> { |
664 | entry: indexmap::map::OccupiedEntry<'a, Key, Item>, |
665 | } |
666 | |
667 | impl<'a> InlineOccupiedEntry<'a> { |
668 | /// Gets a reference to the entry key |
669 | /// |
670 | /// # Examples |
671 | /// |
672 | /// ``` |
673 | /// use toml_edit::Table; |
674 | /// |
675 | /// let mut map = Table::new(); |
676 | /// |
677 | /// assert_eq!("foo" , map.entry("foo" ).key()); |
678 | /// ``` |
679 | pub fn key(&self) -> &str { |
680 | self.entry.key().get() |
681 | } |
682 | |
683 | /// Gets a mutable reference to the entry key |
684 | pub fn key_mut(&mut self) -> KeyMut<'_> { |
685 | use indexmap::map::MutableEntryKey; |
686 | self.entry.key_mut().as_mut() |
687 | } |
688 | |
689 | /// Gets a reference to the value in the entry. |
690 | pub fn get(&self) -> &Value { |
691 | self.entry.get().as_value().unwrap() |
692 | } |
693 | |
694 | /// Gets a mutable reference to the value in the entry. |
695 | pub fn get_mut(&mut self) -> &mut Value { |
696 | self.entry.get_mut().as_value_mut().unwrap() |
697 | } |
698 | |
699 | /// Converts the `OccupiedEntry` into a mutable reference to the value in the entry |
700 | /// with a lifetime bound to the map itself |
701 | pub fn into_mut(self) -> &'a mut Value { |
702 | self.entry.into_mut().as_value_mut().unwrap() |
703 | } |
704 | |
705 | /// Sets the value of the entry, and returns the entry's old value |
706 | pub fn insert(&mut self, value: Value) -> Value { |
707 | let value = Item::Value(value); |
708 | self.entry.insert(value).into_value().unwrap() |
709 | } |
710 | |
711 | /// Takes the value out of the entry, and returns it |
712 | pub fn remove(self) -> Value { |
713 | self.entry.shift_remove().into_value().unwrap() |
714 | } |
715 | } |
716 | |
717 | /// A view into a single empty location in a `IndexMap`. |
718 | pub struct InlineVacantEntry<'a> { |
719 | entry: indexmap::map::VacantEntry<'a, Key, Item>, |
720 | } |
721 | |
722 | impl<'a> InlineVacantEntry<'a> { |
723 | /// Gets a reference to the entry key |
724 | /// |
725 | /// # Examples |
726 | /// |
727 | /// ``` |
728 | /// use toml_edit::Table; |
729 | /// |
730 | /// let mut map = Table::new(); |
731 | /// |
732 | /// assert_eq!("foo" , map.entry("foo" ).key()); |
733 | /// ``` |
734 | pub fn key(&self) -> &str { |
735 | self.entry.key().get() |
736 | } |
737 | |
738 | /// Sets the value of the entry with the `VacantEntry`'s key, |
739 | /// and returns a mutable reference to it |
740 | pub fn insert(self, value: Value) -> &'a mut Value { |
741 | let entry: VacantEntry<'a, Key, Item> = self.entry; |
742 | let value: Item = Item::Value(value); |
743 | entry.insert(value).as_value_mut().unwrap() |
744 | } |
745 | } |
746 | |