1use std::iter::FromIterator;
2
3use crate::key::Key;
4use crate::repr::Decor;
5use crate::table::{Iter, IterMut, KeyValuePairs, TableKeyValue, TableLike};
6use 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)]
11pub 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`
25impl 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 = Table::with_pairs(self.items);
41 t.fmt();
42 t
43 }
44}
45
46/// Formatting
47impl 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
192impl 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 }
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 }
384}
385
386impl std::fmt::Display for InlineTable {
387 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
388 crate::encode::Encode::encode(self, buf:f, input:None, ("", ""))
389 }
390}
391
392impl<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: K, value: V) in iter {
395 let key: Key = key.into();
396 let value: Item = Item::Value(value.into());
397 let value: TableKeyValue = TableKeyValue::new(key, value);
398 self.items
399 .insert(key:InternalString::from(value.key.get()), value);
400 }
401 }
402}
403
404impl<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 = InlineTable::new();
410 table.extend(iter);
411 table
412 }
413}
414
415impl 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: &TableKeyValue)| kv.value.is_value())
424 .map(|(k: InternalString, kv: TableKeyValue)| (k, kv.value.into_value().unwrap())),
425 )
426 }
427}
428
429impl<'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
438fn decorate_inline_table(table: &mut InlineTable) {
439 for (key_decor: &mut Decor, value: &mut Value) in tableimpl Iterator
440 .items
441 .iter_mut()
442 .filter(|&(_, ref kv: &&mut TableKeyValue)| kv.value.is_value())
443 .map(|(_, kv: &mut TableKeyValue)| (&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.
451pub type InlineTableIntoIter = Box<dyn Iterator<Item = (InternalString, Value)>>;
452/// An iterator type over key/value pairs of an inline table.
453pub 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.
455pub type InlineTableIterMut<'a> = Box<dyn Iterator<Item = (KeyMut<'a>, &'a mut Value)> + 'a>;
456
457impl 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, ... }`
542pub(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.
545pub enum InlineEntry<'a> {
546 /// An occupied Entry.
547 Occupied(InlineOccupiedEntry<'a>),
548 /// A vacant Entry.
549 Vacant(InlineVacantEntry<'a>),
550}
551
552impl<'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`.
591pub struct InlineOccupiedEntry<'a> {
592 entry: indexmap::map::OccupiedEntry<'a, InternalString, TableKeyValue>,
593}
594
595impl<'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`.
646pub struct InlineVacantEntry<'a> {
647 entry: indexmap::map::VacantEntry<'a, InternalString, TableKeyValue>,
648 key: Option<Key>,
649}
650
651impl<'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}
680