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 | |