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