| 1 | #[cfg (feature = "std" )] |
| 2 | #[cfg_attr (docsrs, doc(cfg(feature = "std" )))] |
| 3 | #[macro_export ] |
| 4 | /// Create an [`IndexMap`][crate::IndexMap] from a list of key-value pairs |
| 5 | /// |
| 6 | /// ## Example |
| 7 | /// |
| 8 | /// ``` |
| 9 | /// use indexmap::indexmap; |
| 10 | /// |
| 11 | /// let map = indexmap!{ |
| 12 | /// "a" => 1, |
| 13 | /// "b" => 2, |
| 14 | /// }; |
| 15 | /// assert_eq!(map["a" ], 1); |
| 16 | /// assert_eq!(map["b" ], 2); |
| 17 | /// assert_eq!(map.get("c" ), None); |
| 18 | /// |
| 19 | /// // "a" is the first key |
| 20 | /// assert_eq!(map.keys().next(), Some(&"a" )); |
| 21 | /// ``` |
| 22 | macro_rules! indexmap { |
| 23 | ($($key:expr => $value:expr,)+) => { $crate::indexmap!($($key => $value),+) }; |
| 24 | ($($key:expr => $value:expr),*) => { |
| 25 | { |
| 26 | // Note: `stringify!($key)` is just here to consume the repetition, |
| 27 | // but we throw away that string literal during constant evaluation. |
| 28 | const CAP: usize = <[()]>::len(&[$({ stringify!($key); }),*]); |
| 29 | let mut map = $crate::IndexMap::with_capacity(CAP); |
| 30 | $( |
| 31 | map.insert($key, $value); |
| 32 | )* |
| 33 | map |
| 34 | } |
| 35 | }; |
| 36 | } |
| 37 | |
| 38 | #[cfg (feature = "std" )] |
| 39 | #[cfg_attr (docsrs, doc(cfg(feature = "std" )))] |
| 40 | #[macro_export ] |
| 41 | /// Create an [`IndexSet`][crate::IndexSet] from a list of values |
| 42 | /// |
| 43 | /// ## Example |
| 44 | /// |
| 45 | /// ``` |
| 46 | /// use indexmap::indexset; |
| 47 | /// |
| 48 | /// let set = indexset!{ |
| 49 | /// "a" , |
| 50 | /// "b" , |
| 51 | /// }; |
| 52 | /// assert!(set.contains("a" )); |
| 53 | /// assert!(set.contains("b" )); |
| 54 | /// assert!(!set.contains("c" )); |
| 55 | /// |
| 56 | /// // "a" is the first value |
| 57 | /// assert_eq!(set.iter().next(), Some(&"a" )); |
| 58 | /// ``` |
| 59 | macro_rules! indexset { |
| 60 | ($($value:expr,)+) => { $crate::indexset!($($value),+) }; |
| 61 | ($($value:expr),*) => { |
| 62 | { |
| 63 | // Note: `stringify!($value)` is just here to consume the repetition, |
| 64 | // but we throw away that string literal during constant evaluation. |
| 65 | const CAP: usize = <[()]>::len(&[$({ stringify!($value); }),*]); |
| 66 | let mut set = $crate::IndexSet::with_capacity(CAP); |
| 67 | $( |
| 68 | set.insert($value); |
| 69 | )* |
| 70 | set |
| 71 | } |
| 72 | }; |
| 73 | } |
| 74 | |
| 75 | // generate all the Iterator methods by just forwarding to the underlying |
| 76 | // self.iter and mapping its element. |
| 77 | macro_rules! iterator_methods { |
| 78 | // $map_elt is the mapping function from the underlying iterator's element |
| 79 | // same mapping function for both options and iterators |
| 80 | ($map_elt:expr) => { |
| 81 | fn next(&mut self) -> Option<Self::Item> { |
| 82 | self.iter.next().map($map_elt) |
| 83 | } |
| 84 | |
| 85 | fn size_hint(&self) -> (usize, Option<usize>) { |
| 86 | self.iter.size_hint() |
| 87 | } |
| 88 | |
| 89 | fn count(self) -> usize { |
| 90 | self.iter.len() |
| 91 | } |
| 92 | |
| 93 | fn nth(&mut self, n: usize) -> Option<Self::Item> { |
| 94 | self.iter.nth(n).map($map_elt) |
| 95 | } |
| 96 | |
| 97 | fn last(mut self) -> Option<Self::Item> { |
| 98 | self.next_back() |
| 99 | } |
| 100 | |
| 101 | fn collect<C>(self) -> C |
| 102 | where |
| 103 | C: FromIterator<Self::Item>, |
| 104 | { |
| 105 | // NB: forwarding this directly to standard iterators will |
| 106 | // allow it to leverage unstable traits like `TrustedLen`. |
| 107 | self.iter.map($map_elt).collect() |
| 108 | } |
| 109 | }; |
| 110 | } |
| 111 | |
| 112 | macro_rules! double_ended_iterator_methods { |
| 113 | // $map_elt is the mapping function from the underlying iterator's element |
| 114 | // same mapping function for both options and iterators |
| 115 | ($map_elt:expr) => { |
| 116 | fn next_back(&mut self) -> Option<Self::Item> { |
| 117 | self.iter.next_back().map($map_elt) |
| 118 | } |
| 119 | |
| 120 | fn nth_back(&mut self, n: usize) -> Option<Self::Item> { |
| 121 | self.iter.nth_back(n).map($map_elt) |
| 122 | } |
| 123 | }; |
| 124 | } |
| 125 | |
| 126 | // generate `ParallelIterator` methods by just forwarding to the underlying |
| 127 | // self.entries and mapping its elements. |
| 128 | #[cfg (any(feature = "rayon" , feature = "rustc-rayon" ))] |
| 129 | macro_rules! parallel_iterator_methods { |
| 130 | // $map_elt is the mapping function from the underlying iterator's element |
| 131 | ($map_elt:expr) => { |
| 132 | fn drive_unindexed<C>(self, consumer: C) -> C::Result |
| 133 | where |
| 134 | C: UnindexedConsumer<Self::Item>, |
| 135 | { |
| 136 | self.entries |
| 137 | .into_par_iter() |
| 138 | .map($map_elt) |
| 139 | .drive_unindexed(consumer) |
| 140 | } |
| 141 | |
| 142 | // NB: This allows indexed collection, e.g. directly into a `Vec`, but the |
| 143 | // underlying iterator must really be indexed. We should remove this if we |
| 144 | // start having tombstones that must be filtered out. |
| 145 | fn opt_len(&self) -> Option<usize> { |
| 146 | Some(self.entries.len()) |
| 147 | } |
| 148 | }; |
| 149 | } |
| 150 | |
| 151 | // generate `IndexedParallelIterator` methods by just forwarding to the underlying |
| 152 | // self.entries and mapping its elements. |
| 153 | #[cfg (any(feature = "rayon" , feature = "rustc-rayon" ))] |
| 154 | macro_rules! indexed_parallel_iterator_methods { |
| 155 | // $map_elt is the mapping function from the underlying iterator's element |
| 156 | ($map_elt:expr) => { |
| 157 | fn drive<C>(self, consumer: C) -> C::Result |
| 158 | where |
| 159 | C: Consumer<Self::Item>, |
| 160 | { |
| 161 | self.entries.into_par_iter().map($map_elt).drive(consumer) |
| 162 | } |
| 163 | |
| 164 | fn len(&self) -> usize { |
| 165 | self.entries.len() |
| 166 | } |
| 167 | |
| 168 | fn with_producer<CB>(self, callback: CB) -> CB::Output |
| 169 | where |
| 170 | CB: ProducerCallback<Self::Item>, |
| 171 | { |
| 172 | self.entries |
| 173 | .into_par_iter() |
| 174 | .map($map_elt) |
| 175 | .with_producer(callback) |
| 176 | } |
| 177 | }; |
| 178 | } |
| 179 | |