1 use std::iter::FromIterator;
2 
3 use crate::{Array, Item, Table};
4 
5 /// Type representing a TOML array of tables
6 #[derive(Clone, Debug, Default)]
7 pub struct ArrayOfTables {
8     // Always Vec<Item::Table>, just `Item` to make `Index` work
9     pub(crate) span: Option<std::ops::Range<usize>>,
10     pub(crate) values: Vec<Item>,
11 }
12 
13 /// Constructors
14 ///
15 /// See also `FromIterator`
16 impl ArrayOfTables {
17     /// Creates an empty array of tables.
new() -> Self18     pub fn new() -> Self {
19         Default::default()
20     }
21 }
22 
23 /// Formatting
24 impl ArrayOfTables {
25     /// Convert to an inline array
into_array(mut self) -> Array26     pub fn into_array(mut self) -> Array {
27         for value in self.values.iter_mut() {
28             value.make_value();
29         }
30         let mut a = Array::with_vec(self.values);
31         a.fmt();
32         a
33     }
34 
35     /// Returns the location within the original document
span(&self) -> Option<std::ops::Range<usize>>36     pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> {
37         self.span.clone()
38     }
39 
despan(&mut self, input: &str)40     pub(crate) fn despan(&mut self, input: &str) {
41         self.span = None;
42         for value in &mut self.values {
43             value.despan(input);
44         }
45     }
46 }
47 
48 impl ArrayOfTables {
49     /// Returns an iterator over tables.
iter(&self) -> ArrayOfTablesIter<'_>50     pub fn iter(&self) -> ArrayOfTablesIter<'_> {
51         Box::new(self.values.iter().filter_map(Item::as_table))
52     }
53 
54     /// Returns an iterator over tables.
iter_mut(&mut self) -> ArrayOfTablesIterMut<'_>55     pub fn iter_mut(&mut self) -> ArrayOfTablesIterMut<'_> {
56         Box::new(self.values.iter_mut().filter_map(Item::as_table_mut))
57     }
58 
59     /// Returns the length of the underlying Vec.
60     /// To get the actual number of items use `a.iter().count()`.
len(&self) -> usize61     pub fn len(&self) -> usize {
62         self.values.len()
63     }
64 
65     /// Returns true iff `self.len() == 0`.
is_empty(&self) -> bool66     pub fn is_empty(&self) -> bool {
67         self.len() == 0
68     }
69 
70     /// Removes all the tables.
clear(&mut self)71     pub fn clear(&mut self) {
72         self.values.clear()
73     }
74 
75     /// Returns an optional reference to the table.
get(&self, index: usize) -> Option<&Table>76     pub fn get(&self, index: usize) -> Option<&Table> {
77         self.values.get(index).and_then(Item::as_table)
78     }
79 
80     /// Returns an optional mutable reference to the table.
get_mut(&mut self, index: usize) -> Option<&mut Table>81     pub fn get_mut(&mut self, index: usize) -> Option<&mut Table> {
82         self.values.get_mut(index).and_then(Item::as_table_mut)
83     }
84 
85     /// Appends a table to the array.
push(&mut self, table: Table)86     pub fn push(&mut self, table: Table) {
87         self.values.push(Item::Table(table));
88     }
89 
90     /// Removes a table with the given index.
remove(&mut self, index: usize)91     pub fn remove(&mut self, index: usize) {
92         self.values.remove(index);
93     }
94 
95     /// Retains only the elements specified by the `keep` predicate.
96     ///
97     /// In other words, remove all tables for which `keep(&table)` returns `false`.
98     ///
99     /// This method operates in place, visiting each element exactly once in the
100     /// original order, and preserves the order of the retained elements.
retain<F>(&mut self, mut keep: F) where F: FnMut(&Table) -> bool,101     pub fn retain<F>(&mut self, mut keep: F)
102     where
103         F: FnMut(&Table) -> bool,
104     {
105         self.values
106             .retain(|item| item.as_table().map(&mut keep).unwrap_or(false));
107     }
108 }
109 
110 /// An iterator type over `ArrayOfTables`'s values.
111 pub type ArrayOfTablesIter<'a> = Box<dyn Iterator<Item = &'a Table> + 'a>;
112 /// An iterator type over `ArrayOfTables`'s values.
113 pub type ArrayOfTablesIterMut<'a> = Box<dyn Iterator<Item = &'a mut Table> + 'a>;
114 /// An iterator type over `ArrayOfTables`'s values.
115 pub type ArrayOfTablesIntoIter = Box<dyn Iterator<Item = Table>>;
116 
117 impl Extend<Table> for ArrayOfTables {
extend<T: IntoIterator<Item = Table>>(&mut self, iter: T)118     fn extend<T: IntoIterator<Item = Table>>(&mut self, iter: T) {
119         for value in iter {
120             self.push(value);
121         }
122     }
123 }
124 
125 impl FromIterator<Table> for ArrayOfTables {
from_iter<I>(iter: I) -> Self where I: IntoIterator<Item = Table>,126     fn from_iter<I>(iter: I) -> Self
127     where
128         I: IntoIterator<Item = Table>,
129     {
130         let v = iter.into_iter().map(Item::Table);
131         ArrayOfTables {
132             values: v.collect(),
133             span: None,
134         }
135     }
136 }
137 
138 impl IntoIterator for ArrayOfTables {
139     type Item = Table;
140     type IntoIter = ArrayOfTablesIntoIter;
141 
into_iter(self) -> Self::IntoIter142     fn into_iter(self) -> Self::IntoIter {
143         Box::new(
144             self.values
145                 .into_iter()
146                 .filter(|v| v.is_table())
147                 .map(|v| v.into_table().unwrap()),
148         )
149     }
150 }
151 
152 impl<'s> IntoIterator for &'s ArrayOfTables {
153     type Item = &'s Table;
154     type IntoIter = ArrayOfTablesIter<'s>;
155 
into_iter(self) -> Self::IntoIter156     fn into_iter(self) -> Self::IntoIter {
157         self.iter()
158     }
159 }
160 
161 #[cfg(feature = "display")]
162 impl std::fmt::Display for ArrayOfTables {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result163     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
164         // HACK: Without the header, we don't really have a proper way of printing this
165         self.clone().into_array().fmt(f)
166     }
167 }
168