1use std::vec::Vec;
5
6#[cfg(feature = "serde")]
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, PartialEq, Eq)]
11#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12#[cfg_attr(
13 feature = "serde",
14 serde(bound(
15 serialize = "K: Serialize + Eq, V: Serialize",
16 deserialize = "K: Deserialize<'de> + Eq, V: Deserialize<'de>"
17 ))
18)]
19pub struct NeoMap<K, V> {
20 data: Vec<(K, V)>,
21}
22
23impl<K, V> NeoMap<K, V> {
24 pub fn new() -> Self {
25 Self { data: Vec::new() }
26 }
27
28 pub fn insert(&mut self, key: K, value: V) -> Option<V>
29 where
30 K: PartialEq,
31 {
32 for (k, v) in &mut self.data {
33 if *k == key {
34 return Some(core::mem::replace(v, value));
35 }
36 }
37 self.data.push((key, value));
38 None
39 }
40
41 pub fn get(&self, key: &K) -> Option<&V>
47 where
48 K: PartialEq,
49 {
50 self.data.iter().find(|(k, _)| k == key).map(|(_, v)| v)
51 }
52
53 pub fn get_mut(&mut self, key: &K) -> Option<&mut V>
58 where
59 K: PartialEq,
60 {
61 self.data.iter_mut().find(|(k, _)| k == key).map(|(_, v)| v)
62 }
63
64 pub fn remove(&mut self, key: &K) -> Option<V>
76 where
77 K: PartialEq,
78 {
79 self.data
80 .iter()
81 .position(|(k, _)| k == key)
82 .map(|i| self.data.remove(i).1)
83 }
84
85 pub fn len(&self) -> usize {
86 self.data.len()
87 }
88
89 pub fn is_empty(&self) -> bool {
90 self.data.is_empty()
91 }
92
93 pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
94 self.data.iter().map(|(k, v)| (k, v))
95 }
96
97 pub fn contains_key(&self, key: &K) -> bool
99 where
100 K: PartialEq,
101 {
102 self.data.iter().any(|(k, _)| k == key)
103 }
104
105 pub fn keys(&self) -> impl Iterator<Item = &K> {
107 self.data.iter().map(|(k, _)| k)
108 }
109
110 pub fn values(&self) -> impl Iterator<Item = &V> {
112 self.data.iter().map(|(_, v)| v)
113 }
114
115 pub fn remove_strict(&mut self, key: &K, expected_value: &V) -> Result<(), RemoveStrictError>
125 where
126 K: PartialEq,
127 V: PartialEq,
128 {
129 match self.data.iter().position(|(k, _)| k == key) {
130 Some(i) if &self.data[i].1 == expected_value => {
131 self.data.remove(i);
132 Ok(())
133 }
134 Some(_) => Err(RemoveStrictError::ValueMismatch),
135 None => Err(RemoveStrictError::Missing),
136 }
137 }
138}
139
140#[derive(Debug, Clone, Copy, PartialEq, Eq)]
142pub enum RemoveStrictError {
143 Missing,
145 ValueMismatch,
147}
148
149impl core::fmt::Display for RemoveStrictError {
150 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
151 match self {
152 RemoveStrictError::Missing => write!(f, "key not present in map"),
153 RemoveStrictError::ValueMismatch => {
154 write!(f, "value at key did not match expected value")
155 }
156 }
157 }
158}
159
160impl std::error::Error for RemoveStrictError {}
161
162impl<K, V> Default for NeoMap<K, V> {
163 fn default() -> Self {
164 Self::new()
165 }
166}
167
168impl<K, V> IntoIterator for NeoMap<K, V> {
169 type Item = (K, V);
170 type IntoIter = std::vec::IntoIter<(K, V)>;
171 fn into_iter(self) -> Self::IntoIter {
172 self.data.into_iter()
173 }
174}
175
176impl<'a, K, V> IntoIterator for &'a NeoMap<K, V> {
177 type Item = &'a (K, V);
178 type IntoIter = std::slice::Iter<'a, (K, V)>;
179 fn into_iter(self) -> std::slice::Iter<'a, (K, V)> {
180 self.data.iter()
181 }
182}
183
184#[cfg(test)]
185mod tests {
186 use super::*;
187
188 #[test]
189 fn remove_strict_succeeds_on_match() {
190 let mut m: NeoMap<u32, u32> = NeoMap::new();
191 m.insert(1, 100);
192 m.insert(2, 200);
193 assert!(m.remove_strict(&1, &100).is_ok());
194 assert!(!m.contains_key(&1));
195 assert!(m.contains_key(&2));
196 }
197
198 #[test]
199 fn remove_strict_returns_missing_on_absent_key() {
200 let mut m: NeoMap<u32, u32> = NeoMap::new();
201 m.insert(1, 100);
202 assert_eq!(m.remove_strict(&99, &100), Err(RemoveStrictError::Missing));
203 }
204
205 #[test]
206 fn remove_strict_returns_value_mismatch_on_wrong_value() {
207 let mut m: NeoMap<u32, u32> = NeoMap::new();
208 m.insert(1, 100);
209 assert_eq!(
210 m.remove_strict(&1, &999),
211 Err(RemoveStrictError::ValueMismatch)
212 );
213 assert!(m.contains_key(&1));
215 assert_eq!(m.get(&1), Some(&100));
216 }
217}