1use indexmap::map::Iter as MapIter;
2use indexmap::map::Keys as MapKeys;
3use indexmap::map::Values as MapValues;
4use indexmap::IndexMap as Map;
5use std::borrow::Borrow;
6use std::fmt;
7use std::hash::Hash;
8
9use crate::ImplicitClone;
10
11use super::IString;
12use super::Rc;
13
14#[cfg_attr(docsrs, doc(cfg(feature = "map")))]
23#[derive(PartialEq, Eq)]
24pub enum IMap<K: Eq + Hash + ImplicitClone + 'static, V: PartialEq + ImplicitClone + 'static> {
25 Static(&'static [(K, V)]),
27 Rc(Rc<Map<K, V>>),
29}
30
31impl<
33 K: fmt::Debug + Eq + Hash + ImplicitClone + 'static,
34 V: fmt::Debug + PartialEq + ImplicitClone + 'static,
35 > fmt::Debug for IMap<K, V>
36{
37 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
38 match self {
39 Self::Static(a) => a.fmt(f),
40 Self::Rc(a) => a.fmt(f),
41 }
42 }
43}
44
45impl<K: Eq + Hash + ImplicitClone + 'static, V: PartialEq + ImplicitClone + 'static> Clone
46 for IMap<K, V>
47{
48 fn clone(&self) -> Self {
49 match self {
50 Self::Static(a) => Self::Static(a),
51 Self::Rc(a) => Self::Rc(a.clone()),
52 }
53 }
54}
55
56impl<K: Eq + Hash + ImplicitClone + 'static, V: PartialEq + ImplicitClone + 'static> Default
57 for IMap<K, V>
58{
59 fn default() -> Self {
60 Self::Static(&[])
61 }
62}
63
64impl<K: Eq + Hash + ImplicitClone + 'static, V: PartialEq + ImplicitClone + 'static>
65 FromIterator<(K, V)> for IMap<K, V>
66{
67 fn from_iter<I: IntoIterator<Item = (K, V)>>(it: I) -> Self {
68 let vec = it.into_iter().collect::<Map<K, V>>();
69 Self::Rc(Rc::from(vec))
70 }
71}
72
73impl<K: Eq + Hash + ImplicitClone + 'static, V: PartialEq + ImplicitClone + 'static> ImplicitClone
74 for IMap<K, V>
75{
76}
77
78impl<K: Eq + Hash + ImplicitClone + 'static, V: PartialEq + ImplicitClone + 'static>
79 From<&'static [(K, V)]> for IMap<K, V>
80{
81 fn from(a: &'static [(K, V)]) -> IMap<K, V> {
82 IMap::Static(a)
83 }
84}
85
86impl<K: Eq + Hash + ImplicitClone + 'static, V: PartialEq + ImplicitClone + 'static> From<Map<K, V>>
87 for IMap<K, V>
88{
89 fn from(a: Map<K, V>) -> IMap<K, V> {
90 IMap::Rc(Rc::new(a))
91 }
92}
93
94impl<K: Eq + Hash + ImplicitClone + 'static, V: PartialEq + ImplicitClone + 'static>
95 From<Rc<Map<K, V>>> for IMap<K, V>
96{
97 fn from(a: Rc<Map<K, V>>) -> IMap<K, V> {
98 IMap::Rc(a)
99 }
100}
101
102impl<K: Eq + Hash + ImplicitClone + 'static, V: PartialEq + ImplicitClone + 'static>
103 From<&IMap<K, V>> for IMap<K, V>
104{
105 fn from(a: &IMap<K, V>) -> IMap<K, V> {
106 a.clone()
107 }
108}
109
110impl<K: Eq + Hash + ImplicitClone + 'static, V: PartialEq + ImplicitClone + 'static> IMap<K, V> {
111 #[inline]
113 pub fn iter(&self) -> IMapIter<K, V> {
114 match self {
115 Self::Static(a) => IMapIter::Slice(a.iter()),
116 Self::Rc(a) => IMapIter::Map(a.iter()),
117 }
118 }
119
120 #[inline]
122 pub fn keys(&self) -> IMapKeys<K, V> {
123 match self {
124 Self::Static(a) => IMapKeys::Slice(a.iter()),
125 Self::Rc(a) => IMapKeys::Map(a.keys()),
126 }
127 }
128
129 #[inline]
131 pub fn values(&self) -> IMapValues<K, V> {
132 match self {
133 Self::Static(a) => IMapValues::Slice(a.iter()),
134 Self::Rc(a) => IMapValues::Map(a.values()),
135 }
136 }
137
138 #[inline]
142 pub fn len(&self) -> usize {
143 match self {
144 Self::Static(a) => a.len(),
145 Self::Rc(a) => a.len(),
146 }
147 }
148
149 #[inline]
153 pub fn is_empty(&self) -> bool {
154 match self {
155 Self::Static(a) => a.is_empty(),
156 Self::Rc(a) => a.is_empty(),
157 }
158 }
159
160 #[inline]
165 pub fn get<Q>(&self, key: &Q) -> Option<V>
166 where
167 K: Borrow<Q>,
168 Q: Hash + Eq + ?Sized,
169 {
170 match self {
171 Self::Static(a) => a
172 .iter()
173 .find_map(|(k, v)| (k.borrow() == key).then(|| v))
174 .cloned(),
175 Self::Rc(a) => a.get(key).cloned(),
176 }
177 }
178
179 #[inline]
184 pub fn get_key_value<Q>(&self, key: &Q) -> Option<(K, V)>
185 where
186 K: Borrow<Q>,
187 Q: Hash + Eq + ?Sized,
188 {
189 match self {
190 Self::Static(a) => a.iter().find(|(k, _)| k.borrow() == key).cloned(),
191 Self::Rc(a) => a.get_key_value(key).map(|(k, v)| (k.clone(), v.clone())),
192 }
193 }
194
195 #[inline]
197 pub fn get_full<Q>(&self, key: &Q) -> Option<(usize, K, V)>
198 where
199 K: Borrow<Q>,
200 Q: Hash + Eq + ?Sized,
201 {
202 match self {
203 Self::Static(a) => a
204 .iter()
205 .enumerate()
206 .find_map(|(i, (k, v))| (k.borrow() == key).then(|| (i, k.clone(), v.clone()))),
207 Self::Rc(a) => a.get_full(key).map(|(i, k, v)| (i, k.clone(), v.clone())),
208 }
209 }
210
211 #[inline]
217 pub fn get_index(&self, index: usize) -> Option<(K, V)> {
218 match self {
219 Self::Static(a) => a.get(index).cloned(),
220 Self::Rc(a) => a.get_index(index).map(|(k, v)| (k.clone(), v.clone())),
221 }
222 }
223
224 #[inline]
228 pub fn get_index_of<Q>(&self, key: &Q) -> Option<usize>
229 where
230 K: Borrow<Q>,
231 Q: Hash + Eq + ?Sized,
232 {
233 match self {
234 Self::Static(a) => a
235 .iter()
236 .enumerate()
237 .find_map(|(i, (k, _))| (k.borrow() == key).then(|| i)),
238 Self::Rc(a) => a.get_index_of(key),
239 }
240 }
241
242 #[inline]
246 pub fn contains_key<Q>(&self, key: &Q) -> bool
247 where
248 K: Borrow<Q>,
249 Q: Hash + Eq + ?Sized,
250 {
251 match self {
252 Self::Static(a) => a.iter().any(|(k, _)| k.borrow() == key),
253 Self::Rc(a) => a.contains_key(key),
254 }
255 }
256
257 #[inline]
261 pub fn last(&self) -> Option<(K, V)> {
262 match self {
263 Self::Static(a) => a.last().cloned(),
264 Self::Rc(a) => a.last().map(|(k, v)| (k.clone(), v.clone())),
265 }
266 }
267}
268
269impl<V: PartialEq + ImplicitClone + 'static> IMap<IString, V> {
270 #[doc(hidden)]
271 #[inline]
272 pub fn get_static_str(&self, key: &'static str) -> Option<V> {
273 let key = IString::from(key);
274 match self {
275 Self::Static(a) => a.iter().find_map(|(k, v)| (*k == key).then(|| v)).cloned(),
276 Self::Rc(a) => a.get(&key).cloned(),
277 }
278 }
279}
280
281impl<V: PartialEq + ImplicitClone + 'static> IMap<&'static str, V> {
282 #[doc(hidden)]
283 #[inline]
284 pub fn get_static_str(&self, key: &'static str) -> Option<V> {
285 match self {
286 Self::Static(a) => a.iter().find_map(|(k, v)| (*k == key).then(|| v)).cloned(),
287 Self::Rc(a) => a.get(key).cloned(),
288 }
289 }
290}
291
292#[allow(missing_docs, missing_debug_implementations)]
293pub enum IMapIter<'a, K, V> {
294 Slice(std::slice::Iter<'a, (K, V)>),
295 Map(MapIter<'a, K, V>),
296}
297
298impl<'a, K: Eq + Hash + ImplicitClone + 'static, V: PartialEq + ImplicitClone + 'static> Iterator
299 for IMapIter<'a, K, V>
300{
301 type Item = (&'a K, &'a V);
302
303 fn next(&mut self) -> Option<Self::Item> {
304 match self {
305 Self::Slice(it) => it.next().map(|(k, v)| (k, v)),
306 Self::Map(it) => it.next(),
307 }
308 }
309}
310
311impl<'a, K: Eq + Hash + ImplicitClone + 'static, V: PartialEq + ImplicitClone + 'static>
312 DoubleEndedIterator for IMapIter<'a, K, V>
313{
314 fn next_back(&mut self) -> Option<Self::Item> {
315 match self {
316 Self::Slice(it) => it.next_back().map(|(k, v)| (k, v)),
317 Self::Map(it) => it.next_back(),
318 }
319 }
320}
321
322#[allow(missing_docs, missing_debug_implementations)]
323pub enum IMapKeys<'a, K, V> {
324 Slice(std::slice::Iter<'a, (K, V)>),
325 Map(MapKeys<'a, K, V>),
326}
327
328impl<'a, K: Eq + Hash + ImplicitClone + 'static, V: PartialEq + ImplicitClone + 'static> Iterator
329 for IMapKeys<'a, K, V>
330{
331 type Item = &'a K;
332
333 fn next(&mut self) -> Option<Self::Item> {
334 match self {
335 Self::Slice(it) => it.next().map(|(k, _)| k),
336 Self::Map(it) => it.next(),
337 }
338 }
339}
340
341impl<'a, K: Eq + Hash + ImplicitClone + 'static, V: PartialEq + ImplicitClone + 'static>
342 DoubleEndedIterator for IMapKeys<'a, K, V>
343{
344 fn next_back(&mut self) -> Option<Self::Item> {
345 match self {
346 Self::Slice(it) => it.next_back().map(|(k, _)| k),
347 Self::Map(it) => it.next_back(),
348 }
349 }
350}
351
352#[allow(missing_docs, missing_debug_implementations)]
353pub enum IMapValues<'a, K, V> {
354 Slice(std::slice::Iter<'a, (K, V)>),
355 Map(MapValues<'a, K, V>),
356}
357
358impl<'a, K: Eq + Hash + ImplicitClone + 'static, V: PartialEq + ImplicitClone + 'static> Iterator
359 for IMapValues<'a, K, V>
360{
361 type Item = &'a V;
362
363 fn next(&mut self) -> Option<Self::Item> {
364 match self {
365 Self::Slice(it) => it.next().map(|(_, v)| v),
366 Self::Map(it) => it.next(),
367 }
368 }
369}
370
371impl<'a, K: Eq + Hash + ImplicitClone + 'static, V: PartialEq + ImplicitClone + 'static>
372 DoubleEndedIterator for IMapValues<'a, K, V>
373{
374 fn next_back(&mut self) -> Option<Self::Item> {
375 match self {
376 Self::Slice(it) => it.next_back().map(|(_, v)| v),
377 Self::Map(it) => it.next_back(),
378 }
379 }
380}
381
382#[cfg(feature = "serde")]
383impl<K, V> serde::Serialize for IMap<K, V>
384where
385 K: Eq + Hash + ImplicitClone + 'static + serde::Serialize,
386 V: PartialEq + ImplicitClone + 'static + serde::Serialize,
387{
388 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
389 use serde::ser::SerializeMap;
390 let mut seq = serializer.serialize_map(Some(self.len()))?;
391 match self {
392 Self::Static(a) => {
393 for (k, v) in a.iter() {
394 seq.serialize_entry(k, v)?;
395 }
396 }
397 Self::Rc(a) => {
398 for (k, v) in a.iter() {
399 seq.serialize_entry(k, v)?;
400 }
401 }
402 }
403 seq.end()
404 }
405}
406
407#[cfg(feature = "serde")]
408impl<'de, K, V> serde::Deserialize<'de> for IMap<K, V>
409where
410 K: Eq + Hash + ImplicitClone + 'static + serde::Deserialize<'de>,
411 V: PartialEq + ImplicitClone + 'static + serde::Deserialize<'de>,
412{
413 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
414 <Map<K, V> as serde::Deserialize>::deserialize(deserializer).map(IMap::<K, V>::from)
415 }
416}
417
418#[cfg(test)]
419mod test_map {
420 use super::*;
421
422 #[test]
423 fn map_in_map() {
424 let map_1 = [
425 (IString::from("foo1"), 1),
426 (IString::from("bar1"), 2),
427 (IString::from("baz1"), 3),
428 ]
429 .into_iter()
430 .collect::<IMap<IString, u32>>();
431 let map_2 = [
432 (IString::from("foo2"), 4),
433 (IString::from("bar2"), 5),
434 (IString::from("baz2"), 6),
435 ]
436 .into_iter()
437 .collect::<IMap<IString, u32>>();
438 let map_of_map = [("map_1", map_1), ("map_2", map_2)]
439 .into_iter()
440 .collect::<IMap<&'static str, IMap<IString, u32>>>();
441 let flattened_vec = map_of_map
442 .iter()
443 .flat_map(|(_key, map)| map.iter().collect::<Vec<(_, _)>>())
444 .collect::<Vec<(_, _)>>();
445 assert_eq!(
447 flattened_vec,
448 [
449 (&IString::from("foo1"), &1),
450 (&IString::from("bar1"), &2),
451 (&IString::from("baz1"), &3),
452 (&IString::from("foo2"), &4),
453 (&IString::from("bar2"), &5),
454 (&IString::from("baz2"), &6),
455 ]
456 );
457 }
458
459 #[test]
460 fn static_map() {
461 const _MAP: IMap<&str, u32> = IMap::Static(&[("foo", 1)]);
462 }
463
464 #[test]
465 fn floats_in_map() {
466 const _MAP_F32: IMap<u32, f32> = IMap::Static(&[]);
467 const _MAP_F64: IMap<u32, f64> = IMap::Static(&[]);
468 }
469
470 #[test]
471 fn from() {
472 let x: IMap<u32, u32> = IMap::Static(&[]);
473 let _out = IMap::from(&x);
474 }
475}