1use std::cmp::Ordering;
16
17#[derive(Debug, Clone)]
18pub struct SortedVecMap<K: Ord, V> {
19 entries: Vec<(K, V)>,
20}
21
22impl<K: Ord, V> Default for SortedVecMap<K, V> {
23 fn default() -> Self {
24 Self::new()
25 }
26}
27
28impl<K: Ord, V> SortedVecMap<K, V> {
29 pub fn new() -> Self {
30 Self {
31 entries: Vec::new(),
32 }
33 }
34
35 pub fn with_capacity(cap: usize) -> Self {
36 Self {
37 entries: Vec::with_capacity(cap),
38 }
39 }
40
41 pub fn from_sorted_unique(entries: Vec<(K, V)>) -> Self {
45 debug_assert!(
46 entries.windows(2).all(|w| w[0].0 < w[1].0),
47 "from_sorted_unique requires strictly sorted unique keys"
48 );
49 Self { entries }
50 }
51
52 pub fn from_iter_unsorted<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self
54 where
55 K: Clone,
56 {
57 let mut entries: Vec<(K, V)> = iter.into_iter().collect();
58 entries.sort_by(|a, b| a.0.cmp(&b.0));
59 let mut deduped: Vec<(K, V)> = Vec::with_capacity(entries.len());
62 for (k, v) in entries.into_iter() {
63 if let Some(last) = deduped.last_mut() {
64 if last.0 == k {
65 last.1 = v;
66 continue;
67 }
68 }
69 deduped.push((k, v));
70 }
71 Self { entries: deduped }
72 }
73
74 pub fn len(&self) -> usize {
75 self.entries.len()
76 }
77
78 pub fn is_empty(&self) -> bool {
79 self.entries.is_empty()
80 }
81
82 pub fn get(&self, key: &K) -> Option<&V> {
85 self.entries
86 .binary_search_by(|(k, _)| k.cmp(key))
87 .ok()
88 .map(|i| &self.entries[i].1)
89 }
90
91 pub fn contains_key(&self, key: &K) -> bool {
92 self.entries
93 .binary_search_by(|(k, _)| k.cmp(key))
94 .is_ok()
95 }
96
97 pub fn insert(&mut self, key: K, value: V) -> Option<V> {
100 match self.entries.binary_search_by(|(k, _)| k.cmp(&key)) {
101 Ok(i) => Some(std::mem::replace(&mut self.entries[i].1, value)),
102 Err(i) => {
103 self.entries.insert(i, (key, value));
104 None
105 }
106 }
107 }
108
109 pub fn remove(&mut self, key: &K) -> Option<V> {
110 match self.entries.binary_search_by(|(k, _)| k.cmp(key)) {
111 Ok(i) => Some(self.entries.remove(i).1),
112 Err(_) => None,
113 }
114 }
115
116 pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> + '_ {
118 self.entries.iter().map(|(k, v)| (k, v))
119 }
120
121 pub fn range<Q>(&self, start: &Q, end: &Q) -> impl Iterator<Item = (&K, &V)> + '_
123 where
124 K: std::borrow::Borrow<Q>,
125 Q: Ord + ?Sized,
126 {
127 let lo = self
129 .entries
130 .binary_search_by(|(k, _)| match k.borrow().cmp(start) {
131 Ordering::Less => Ordering::Less,
132 _ => Ordering::Greater,
133 })
134 .unwrap_or_else(|i| i);
135 let hi = self
136 .entries
137 .binary_search_by(|(k, _)| match k.borrow().cmp(end) {
138 Ordering::Less => Ordering::Less,
139 _ => Ordering::Greater,
140 })
141 .unwrap_or_else(|i| i);
142 self.entries[lo..hi].iter().map(|(k, v)| (k, v))
143 }
144}
145
146#[cfg(test)]
147mod tests {
148 use super::*;
149
150 #[test]
151 fn binary_search_lookup() {
152 let mut m = SortedVecMap::new();
153 for k in 0..100i32 {
154 m.insert(k, k * 10);
155 }
156 for k in 0..100 {
157 assert_eq!(m.get(&k), Some(&(k * 10)));
158 }
159 assert_eq!(m.get(&100), None);
160 assert_eq!(m.get(&-1), None);
161 }
162
163 #[test]
164 fn iter_is_sorted() {
165 let m = SortedVecMap::from_iter_unsorted(vec![
166 (3, "c"),
167 (1, "a"),
168 (4, "d"),
169 (2, "b"),
170 ]);
171 let keys: Vec<i32> = m.iter().map(|(k, _)| *k).collect();
172 assert_eq!(keys, vec![1, 2, 3, 4]);
173 }
174
175 #[test]
176 fn from_iter_unsorted_dedup_last_wins() {
177 let m = SortedVecMap::from_iter_unsorted(vec![(1, "a"), (1, "b"), (1, "c")]);
178 assert_eq!(m.get(&1), Some(&"c"));
179 assert_eq!(m.len(), 1);
180 }
181
182 #[test]
183 fn range_query() {
184 let m: SortedVecMap<i32, &str> = SortedVecMap::from_sorted_unique(vec![
185 (1, "a"),
186 (2, "b"),
187 (3, "c"),
188 (4, "d"),
189 (5, "e"),
190 ]);
191 let r: Vec<_> = m.range(&2, &5).map(|(k, _)| *k).collect();
192 assert_eq!(r, vec![2, 3, 4]);
193 }
194
195 #[test]
196 fn from_sorted_unique_debug_panics_on_unsorted() {
197 if cfg!(debug_assertions) {
199 let result = std::panic::catch_unwind(|| {
200 SortedVecMap::from_sorted_unique(vec![(2, "b"), (1, "a")])
201 });
202 assert!(result.is_err());
203 }
204 }
205}