1 | #[cfg (has_std)] |
2 | #[macro_export ] |
3 | /// Create an `IndexMap` from a list of key-value pairs |
4 | /// |
5 | /// ## Example |
6 | /// |
7 | /// ``` |
8 | /// use indexmap::indexmap; |
9 | /// |
10 | /// let map = indexmap!{ |
11 | /// "a" => 1, |
12 | /// "b" => 2, |
13 | /// }; |
14 | /// assert_eq!(map["a" ], 1); |
15 | /// assert_eq!(map["b" ], 2); |
16 | /// assert_eq!(map.get("c" ), None); |
17 | /// |
18 | /// // "a" is the first key |
19 | /// assert_eq!(map.keys().next(), Some(&"a" )); |
20 | /// ``` |
21 | macro_rules! indexmap { |
22 | (@single $($x:tt)*) => (()); |
23 | (@count $($rest:expr),*) => (<[()]>::len(&[$($crate::indexmap!(@single $rest)),*])); |
24 | |
25 | ($($key:expr => $value:expr,)+) => { $crate::indexmap!($($key => $value),+) }; |
26 | ($($key:expr => $value:expr),*) => { |
27 | { |
28 | let _cap = $crate::indexmap!(@count $($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 (has_std)] |
39 | #[macro_export ] |
40 | /// Create an `IndexSet` from a list of values |
41 | /// |
42 | /// ## Example |
43 | /// |
44 | /// ``` |
45 | /// use indexmap::indexset; |
46 | /// |
47 | /// let set = indexset!{ |
48 | /// "a" , |
49 | /// "b" , |
50 | /// }; |
51 | /// assert!(set.contains("a" )); |
52 | /// assert!(set.contains("b" )); |
53 | /// assert!(!set.contains("c" )); |
54 | /// |
55 | /// // "a" is the first value |
56 | /// assert_eq!(set.iter().next(), Some(&"a" )); |
57 | /// ``` |
58 | macro_rules! indexset { |
59 | (@single $($x:tt)*) => (()); |
60 | (@count $($rest:expr),*) => (<[()]>::len(&[$($crate::indexset!(@single $rest)),*])); |
61 | |
62 | ($($value:expr,)+) => { $crate::indexset!($($value),+) }; |
63 | ($($value:expr),*) => { |
64 | { |
65 | let _cap = $crate::indexset!(@count $($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 | |