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