1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
use super::prelude::*;

#[ cfg (not (fuzzing)) ]
//pub use std_hash::*;
pub use fast_hash::*;

#[ cfg (fuzzing) ]
pub use test_hash::*;

mod std_hash {
	pub use std::collections::HashMap;
	pub use std::collections::HashSet;
}

mod fast_hash {
	pub use ahash::AHashMap as HashMap;
	pub use ahash::AHashSet as HashSet;
}

#[ cfg (fuzzing) ]
mod test_hash {
	pub use std::collections::BTreeSet as HashSet;
	pub use super::test_map::HashMap;
}

#[ cfg (fuzzing) ]
mod test_map;

pub struct MapToIndex <Item> {
	items: Vec <Item>,
	indexes: HashMap <Item, usize>,
}

impl <Item: Clone + Eq + Hash + Ord> MapToIndex <Item> {

	#[ inline ]
	#[ must_use ]
	pub fn new () -> Self {
		Self {
			items: Vec::new (),
			indexes: HashMap::new (),
		}
	}

	#[ inline ]
	#[ must_use ]
	pub fn len (& self) -> usize {
		self.items.len ()
	}

	#[ inline ]
	#[ must_use ]
	pub fn is_empty (& self) -> bool {
		self.items.is_empty ()
	}

	#[ inline ]
	pub fn insert (& mut self, item: Item) -> usize {
		* self.indexes.entry (item.clone ()).or_insert_with (|| {
			let idx = self.items.len ();
			self.items.push (item);
			idx
		})
	}

}

impl <Item: Clone + Eq + Hash + Ord> Default for MapToIndex <Item> {

	#[ inline ]
	fn default () -> Self {
		Self::new ()
	}

}

impl <Item> Deref for MapToIndex <Item> {

	type Target = [Item];

	#[ inline ]
	fn deref (& self) -> & [Item] {
		& self.items
	}

}

impl <Item: Clone + Eq + Hash + Ord> FromIterator <Item> for MapToIndex <Item> {

	#[ inline ]
	fn from_iter <Iter: IntoIterator <Item = Item>> (iter: Iter) -> Self {
		iter.into_iter ()
			.fold (Self::new (), |mut map, item| { map.insert (item); map })
	}

}

impl <Item: Eq + Hash + Ord> Index <& Item> for MapToIndex <Item> {

	type Output = usize;

	#[ inline ]
	fn index (& self, item: & Item) -> & usize {
		self.indexes.get (item).unwrap ()
	}

}