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 /// The location within the original document 36 /// 37 /// This generally requires an [`ImDocument`][crate::ImDocument]. span(&self) -> Option<std::ops::Range<usize>>38 pub fn span(&self) -> Option<std::ops::Range<usize>> { 39 self.span.clone() 40 } 41 despan(&mut self, input: &str)42 pub(crate) fn despan(&mut self, input: &str) { 43 self.span = None; 44 for value in &mut self.values { 45 value.despan(input); 46 } 47 } 48 } 49 50 impl ArrayOfTables { 51 /// Returns an iterator over tables. iter(&self) -> ArrayOfTablesIter<'_>52 pub fn iter(&self) -> ArrayOfTablesIter<'_> { 53 Box::new(self.values.iter().filter_map(Item::as_table)) 54 } 55 56 /// Returns an iterator over tables. iter_mut(&mut self) -> ArrayOfTablesIterMut<'_>57 pub fn iter_mut(&mut self) -> ArrayOfTablesIterMut<'_> { 58 Box::new(self.values.iter_mut().filter_map(Item::as_table_mut)) 59 } 60 61 /// Returns the length of the underlying Vec. 62 /// To get the actual number of items use `a.iter().count()`. len(&self) -> usize63 pub fn len(&self) -> usize { 64 self.values.len() 65 } 66 67 /// Returns true if `self.len() == 0`. is_empty(&self) -> bool68 pub fn is_empty(&self) -> bool { 69 self.len() == 0 70 } 71 72 /// Removes all the tables. clear(&mut self)73 pub fn clear(&mut self) { 74 self.values.clear(); 75 } 76 77 /// Returns an optional reference to the table. get(&self, index: usize) -> Option<&Table>78 pub fn get(&self, index: usize) -> Option<&Table> { 79 self.values.get(index).and_then(Item::as_table) 80 } 81 82 /// Returns an optional mutable reference to the table. get_mut(&mut self, index: usize) -> Option<&mut Table>83 pub fn get_mut(&mut self, index: usize) -> Option<&mut Table> { 84 self.values.get_mut(index).and_then(Item::as_table_mut) 85 } 86 87 /// Appends a table to the array. push(&mut self, table: Table)88 pub fn push(&mut self, table: Table) { 89 self.values.push(Item::Table(table)); 90 } 91 92 /// Removes a table with the given index. remove(&mut self, index: usize)93 pub fn remove(&mut self, index: usize) { 94 self.values.remove(index); 95 } 96 97 /// Retains only the elements specified by the `keep` predicate. 98 /// 99 /// In other words, remove all tables for which `keep(&table)` returns `false`. 100 /// 101 /// This method operates in place, visiting each element exactly once in the 102 /// original order, and preserves the order of the retained elements. retain<F>(&mut self, mut keep: F) where F: FnMut(&Table) -> bool,103 pub fn retain<F>(&mut self, mut keep: F) 104 where 105 F: FnMut(&Table) -> bool, 106 { 107 self.values 108 .retain(|item| item.as_table().map(&mut keep).unwrap_or(false)); 109 } 110 } 111 112 /// An iterator type over `ArrayOfTables`'s values. 113 pub type ArrayOfTablesIter<'a> = Box<dyn Iterator<Item = &'a Table> + 'a>; 114 /// An iterator type over `ArrayOfTables`'s values. 115 pub type ArrayOfTablesIterMut<'a> = Box<dyn Iterator<Item = &'a mut Table> + 'a>; 116 /// An iterator type over `ArrayOfTables`'s values. 117 pub type ArrayOfTablesIntoIter = Box<dyn Iterator<Item = Table>>; 118 119 impl Extend<Table> for ArrayOfTables { extend<T: IntoIterator<Item = Table>>(&mut self, iter: T)120 fn extend<T: IntoIterator<Item = Table>>(&mut self, iter: T) { 121 for value in iter { 122 self.push(value); 123 } 124 } 125 } 126 127 impl FromIterator<Table> for ArrayOfTables { from_iter<I>(iter: I) -> Self where I: IntoIterator<Item = Table>,128 fn from_iter<I>(iter: I) -> Self 129 where 130 I: IntoIterator<Item = Table>, 131 { 132 let v = iter.into_iter().map(Item::Table); 133 ArrayOfTables { 134 values: v.collect(), 135 span: None, 136 } 137 } 138 } 139 140 impl IntoIterator for ArrayOfTables { 141 type Item = Table; 142 type IntoIter = ArrayOfTablesIntoIter; 143 into_iter(self) -> Self::IntoIter144 fn into_iter(self) -> Self::IntoIter { 145 Box::new( 146 self.values 147 .into_iter() 148 .filter(|v| v.is_table()) 149 .map(|v| v.into_table().unwrap()), 150 ) 151 } 152 } 153 154 impl<'s> IntoIterator for &'s ArrayOfTables { 155 type Item = &'s Table; 156 type IntoIter = ArrayOfTablesIter<'s>; 157 into_iter(self) -> Self::IntoIter158 fn into_iter(self) -> Self::IntoIter { 159 self.iter() 160 } 161 } 162 163 #[cfg(feature = "display")] 164 impl std::fmt::Display for ArrayOfTables { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result165 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 166 // HACK: Without the header, we don't really have a proper way of printing this 167 self.clone().into_array().fmt(f) 168 } 169 } 170