1use std::ops::Index;
7
8pub trait OrdMapValue<K>
12where
13 K: std::cmp::Eq + std::hash::Hash + Clone,
14{
15 fn key(&self) -> Option<K>;
17}
18
19#[derive(Clone, PartialEq)]
21pub struct OrdMap<K, V>
22where
23 V: OrdMapValue<K>,
24 K: std::cmp::Eq + std::hash::Hash + Clone,
25{
26 vec: Vec<V>,
28 map: std::collections::HashMap<K, usize>,
30}
31
32impl<K, V> Default for OrdMap<K, V>
33where
34 V: OrdMapValue<K>,
35 K: std::cmp::Eq + std::hash::Hash + Clone,
36{
37 fn default() -> Self {
38 Self {
39 vec: Default::default(),
40 map: Default::default(),
41 }
42 }
43}
44
45impl<K, V> std::fmt::Debug for OrdMap<K, V>
46where
47 V: OrdMapValue<K> + std::fmt::Debug,
48 K: std::cmp::Eq + std::hash::Hash + Clone,
49{
50 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51 f.debug_struct("OrdMap").field("vec", &self.vec).finish()
52 }
53}
54
55impl<K, V> From<Vec<V>> for OrdMap<K, V>
56where
57 V: OrdMapValue<K>,
58 K: std::cmp::Eq + std::hash::Hash + Clone,
59{
60 fn from(vec: Vec<V>) -> Self {
61 let mut map = std::collections::HashMap::new();
62 for (i, item) in vec.iter().enumerate() {
64 if let Some(key) = item.key() {
65 map.insert(key, i);
66 }
67 }
68
69 Self { vec, map }
70 }
71}
72
73impl<K, V> OrdMap<K, V>
74where
75 V: OrdMapValue<K>,
76 K: std::cmp::Eq + std::hash::Hash + Clone,
77{
78 pub fn iter(&self) -> std::slice::Iter<'_, V> {
80 self.vec.iter()
81 }
82
83 pub fn len(&self) -> usize {
85 self.vec.len()
86 }
87
88 pub fn is_empty(&self) -> bool {
90 self.vec.is_empty()
91 }
92
93 pub fn try_push(&mut self, item: V) -> Result<(), (K, K)> {
97 if let Some(key) = item.key() {
98 match self.map.entry(key) {
99 std::collections::hash_map::Entry::Vacant(entry) => entry.insert(self.vec.len()),
100 std::collections::hash_map::Entry::Occupied(entry) => {
101 return Err((entry.key().clone(), item.key().expect("ord_map error")));
102 }
103 };
104 }
105 self.vec.push(item);
106 Ok(())
107 }
108
109 pub fn get(&self, key: &K) -> Option<&V> {
111 self.map.get(key).map(|index| &self.vec[*index])
112 }
113
114 pub fn keys(&self) -> std::collections::hash_map::Keys<'_, K, usize> {
116 self.map.keys()
117 }
118
119 pub fn first(&self) -> Option<&V> {
121 self.vec.first()
122 }
123}
124
125impl<K, V> Index<usize> for OrdMap<K, V>
126where
127 V: OrdMapValue<K>,
128 K: std::cmp::Eq + std::hash::Hash + Clone,
129{
130 type Output = V;
131
132 fn index(&self, index: usize) -> &Self::Output {
133 &self.vec[index]
134 }
135}
136
137impl<K, V> Index<&K> for OrdMap<K, V>
138where
139 V: OrdMapValue<K>,
140 K: std::cmp::Eq + std::hash::Hash + Clone,
141{
142 type Output = V;
143
144 fn index(&self, key: &K) -> &Self::Output {
145 &self.vec[*self.map.get(key).expect("key not found")]
146 }
147}