1#![doc = include_str!("../ABOUT.md")]
8#![doc(
9 html_logo_url = "https://raw.githubusercontent.com/boa-dev/boa/main/assets/logo_black.svg",
10 html_favicon_url = "https://raw.githubusercontent.com/boa-dev/boa/main/assets/logo_black.svg"
11)]
12use std::{
13 borrow::Borrow,
14 collections::{BTreeMap, btree_map},
15 fmt,
16 hash::{Hash, Hasher},
17 iter::FusedIterator,
18 ops::{Index, IndexMut},
19};
20
21use arrayvec::ArrayVec;
22
23mod entry;
24
25pub use entry::{Entry, OccupiedEntry, VacantEntry};
26
27use Entry::{Occupied, Vacant};
28
29#[derive(Clone)]
32pub struct SmallBTreeMap<K, V, const ARRAY_SIZE: usize> {
33 inner: Inner<K, V, ARRAY_SIZE>,
34}
35
36#[derive(Debug, Clone)]
37enum Inner<K, V, const ARRAY_SIZE: usize> {
38 Inline(ArrayVec<(K, V), ARRAY_SIZE>),
39 Heap(BTreeMap<K, V>),
40}
41
42#[derive(Clone)]
49pub struct Iter<'a, K, V> {
50 inner: InnerIter<'a, K, V>,
51}
52
53#[derive(Clone)]
54enum InnerIter<'a, K, V> {
55 Inline(std::slice::Iter<'a, (K, V)>),
56 Heap(btree_map::Iter<'a, K, V>),
57}
58
59impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for Iter<'_, K, V> {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 match &self.inner {
62 InnerIter::Inline(i) => f.debug_tuple("Inline").field(i).finish(),
63 InnerIter::Heap(h) => f.debug_tuple("Heap").field(h).finish(),
64 }
65 }
66}
67
68impl<K, V> Default for Iter<'_, K, V> {
69 fn default() -> Self {
71 Self {
72 inner: InnerIter::Inline(std::slice::Iter::default()),
73 }
74 }
75}
76
77pub struct IterMut<'a, K, V> {
84 inner: InnerIterMut<'a, K, V>,
85}
86
87enum InnerIterMut<'a, K, V> {
88 Inline(std::slice::IterMut<'a, (K, V)>),
89 Heap(btree_map::IterMut<'a, K, V>),
90}
91
92impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IterMut<'_, K, V> {
93 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94 match &self.inner {
95 InnerIterMut::Inline(i) => f.debug_tuple("Inline").field(i).finish(),
96 InnerIterMut::Heap(h) => f.debug_tuple("Heap").field(h).finish(),
97 }
98 }
99}
100
101impl<K, V> Default for IterMut<'_, K, V> {
102 fn default() -> Self {
104 Self {
105 inner: InnerIterMut::Inline(std::slice::IterMut::default()),
106 }
107 }
108}
109
110pub struct IntoIter<K, V, const ARRAY_SIZE: usize> {
117 inner: InnerIntoIter<K, V, ARRAY_SIZE>,
118}
119
120enum InnerIntoIter<K, V, const ARRAY_SIZE: usize> {
121 Inline(arrayvec::IntoIter<(K, V), ARRAY_SIZE>),
122 Heap(btree_map::IntoIter<K, V>),
123}
124
125impl<K: fmt::Debug, V: fmt::Debug, const ARRAY_SIZE: usize> fmt::Debug
126 for IntoIter<K, V, ARRAY_SIZE>
127{
128 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129 match &self.inner {
130 InnerIntoIter::Inline(i) => f.debug_tuple("Inline").field(i).finish(),
131 InnerIntoIter::Heap(h) => f.debug_tuple("Heap").field(h).finish(),
132 }
133 }
134}
135
136impl<K, V, const ARRAY_SIZE: usize> Default for IntoIter<K, V, ARRAY_SIZE> {
137 fn default() -> Self {
139 Self {
140 inner: InnerIntoIter::Inline(ArrayVec::new().into_iter()),
141 }
142 }
143}
144
145impl<K, V, const ARRAY_SIZE: usize> SmallBTreeMap<K, V, ARRAY_SIZE> {
146 #[must_use]
148 pub const fn new() -> Self {
149 Self {
150 inner: Inner::Inline(ArrayVec::new_const()),
151 }
152 }
153
154 pub fn clear(&mut self) {
159 match &mut self.inner {
160 Inner::Inline(v) => v.clear(),
161 Inner::Heap(h) => h.clear(),
162 }
163 }
164
165 pub fn get<Q>(&self, key: &Q) -> Option<&V>
170 where
171 K: Borrow<Q> + Ord + Eq,
172 Q: ?Sized + Ord + Eq,
173 {
174 match &self.inner {
175 Inner::Inline(v) => v.iter().find(|(k, _)| k.borrow() == key).map(|(_, v)| v),
176 Inner::Heap(h) => h.get(key),
177 }
178 }
179
180 #[allow(clippy::map_identity)]
185 pub fn get_key_value<Q>(&self, key: &Q) -> Option<(&K, &V)>
186 where
187 K: Borrow<Q> + Ord + Eq,
188 Q: ?Sized + Ord + Eq,
189 {
190 match &self.inner {
191 Inner::Inline(v) => v
192 .iter()
193 .find(|(k, _)| k.borrow() == key)
194 .map(|(k, v)| (k, v)),
195 Inner::Heap(h) => h.get_key_value(key),
196 }
197 }
198
199 pub fn contains_key<Q>(&self, key: &Q) -> bool
204 where
205 K: Borrow<Q> + Ord + Eq,
206 Q: ?Sized + Ord + Eq,
207 {
208 self.get(key).is_some()
209 }
210
211 pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
216 where
217 K: Borrow<Q> + Ord + Eq,
218 Q: ?Sized + Ord + Eq,
219 {
220 match &mut self.inner {
221 Inner::Inline(v) => v
222 .iter_mut()
223 .find(|(k, _)| k.borrow() == key)
224 .map(|(_, v)| v),
225 Inner::Heap(h) => h.get_mut(key),
226 }
227 }
228
229 pub fn insert(&mut self, key: K, value: V) -> Option<V>
240 where
241 K: Eq + Ord,
242 {
243 match self.entry(key) {
244 Occupied(mut entry) => Some(entry.insert(value)),
245 Vacant(entry) => {
246 entry.insert(value);
247 None
248 }
249 }
250 }
251
252 pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
258 where
259 K: Borrow<Q> + Ord + Eq,
260 Q: ?Sized + Ord + Eq,
261 {
262 self.remove_entry(key).map(|(_, v)| v)
263 }
264
265 pub fn remove_entry<Q>(&mut self, key: &Q) -> Option<(K, V)>
271 where
272 K: Borrow<Q> + Ord,
273 Q: ?Sized + Ord,
274 {
275 match &mut self.inner {
276 Inner::Inline(v) => v
277 .iter()
278 .position(|(k, _)| k.borrow() == key)
279 .map(|idx| v.remove(idx)),
280 Inner::Heap(h) => h.remove_entry(key),
281 }
282 }
283
284 pub fn retain<F>(&mut self, mut f: F)
288 where
289 K: Ord,
290 F: FnMut(&K, &mut V) -> bool,
291 {
292 match &mut self.inner {
293 Inner::Inline(v) => v.retain(|(k, v)| f(k, v)),
294 Inner::Heap(h) => h.retain(f),
295 }
296 }
297
298 pub fn append<const OTHER_SIZE: usize>(&mut self, other: &mut SmallBTreeMap<K, V, OTHER_SIZE>)
303 where
304 K: Ord + Eq,
305 {
306 if other.is_empty() {
307 return;
308 }
309
310 let inline = matches!(other.inner, Inner::Inline(_));
311
312 let other = std::mem::replace(
313 other,
314 SmallBTreeMap {
315 inner: if inline {
316 Inner::Inline(ArrayVec::new())
317 } else {
318 Inner::Heap(BTreeMap::new())
319 },
320 },
321 );
322
323 self.extend(other);
324 }
325
326 pub fn entry(&mut self, key: K) -> Entry<'_, K, V, ARRAY_SIZE>
328 where
329 K: Eq + Ord,
330 {
331 match &mut self.inner {
332 Inner::Inline(array) => {
333 let Some(index) = array.iter().position(|(k, _)| *k == key) else {
334 return Vacant(VacantEntry {
335 inner: entry::InnerVacant::Inline(entry::InlineVacantEntry {
336 key,
337 map: self,
338 }),
339 });
340 };
341
342 match &mut self.inner {
346 Inner::Inline(array) => Occupied(OccupiedEntry {
347 inner: entry::InnerOccupied::Inline(entry::InlineOccupiedEntry {
348 index,
349 array,
350 }),
351 }),
352 Inner::Heap(_) => unreachable!(),
353 }
354 }
355 Inner::Heap(_) => match &mut self.inner {
357 Inner::Heap(h) => match h.entry(key) {
358 btree_map::Entry::Vacant(entry) => Vacant(VacantEntry {
359 inner: entry::InnerVacant::Heap(entry),
360 }),
361 btree_map::Entry::Occupied(entry) => Occupied(OccupiedEntry {
362 inner: entry::InnerOccupied::Heap(entry),
363 }),
364 },
365 Inner::Inline(_) => unreachable!(),
366 },
367 }
368 }
369}
370
371impl<'a, K, V, const ARRAY_SIZE: usize> IntoIterator for &'a SmallBTreeMap<K, V, ARRAY_SIZE> {
372 type Item = (&'a K, &'a V);
373 type IntoIter = Iter<'a, K, V>;
374
375 fn into_iter(self) -> Self::IntoIter {
376 self.iter()
377 }
378}
379
380impl<'a, K, V> Iterator for Iter<'a, K, V> {
381 type Item = (&'a K, &'a V);
382
383 #[allow(clippy::map_identity)]
384 fn next(&mut self) -> Option<Self::Item> {
385 match &mut self.inner {
386 InnerIter::Inline(i) => i.next().map(|(k, v)| (k, v)),
387 InnerIter::Heap(h) => h.next(),
388 }
389 }
390
391 fn size_hint(&self) -> (usize, Option<usize>) {
392 match &self.inner {
393 InnerIter::Inline(i) => i.size_hint(),
394 InnerIter::Heap(h) => h.size_hint(),
395 }
396 }
397
398 #[allow(clippy::map_identity)]
399 fn last(self) -> Option<(&'a K, &'a V)> {
400 match self.inner {
401 InnerIter::Inline(i) => i.last().map(|(k, v)| (k, v)),
402 InnerIter::Heap(h) => h.last(),
403 }
404 }
405}
406
407impl<K, V> FusedIterator for Iter<'_, K, V> {}
408
409impl<'a, K: 'a, V: 'a> DoubleEndedIterator for Iter<'a, K, V> {
410 #[allow(clippy::map_identity)]
411 fn next_back(&mut self) -> Option<(&'a K, &'a V)> {
412 match &mut self.inner {
413 InnerIter::Inline(i) => i.next_back().map(|(k, v)| (k, v)),
414 InnerIter::Heap(h) => h.next_back(),
415 }
416 }
417}
418
419impl<K, V> ExactSizeIterator for Iter<'_, K, V> {
420 fn len(&self) -> usize {
421 match &self.inner {
422 InnerIter::Inline(i) => i.len(),
423 InnerIter::Heap(h) => h.len(),
424 }
425 }
426}
427
428impl<'a, K, V, const ARRAY_SIZE: usize> IntoIterator for &'a mut SmallBTreeMap<K, V, ARRAY_SIZE> {
429 type Item = (&'a K, &'a mut V);
430 type IntoIter = IterMut<'a, K, V>;
431
432 fn into_iter(self) -> Self::IntoIter {
433 self.iter_mut()
434 }
435}
436
437impl<'a, K, V> Iterator for IterMut<'a, K, V> {
438 type Item = (&'a K, &'a mut V);
439
440 fn next(&mut self) -> Option<Self::Item> {
441 match &mut self.inner {
442 InnerIterMut::Inline(i) => i.next().map(|(k, v)| (&*k, v)),
443 InnerIterMut::Heap(h) => h.next(),
444 }
445 }
446
447 fn size_hint(&self) -> (usize, Option<usize>) {
448 match &self.inner {
449 InnerIterMut::Inline(i) => i.size_hint(),
450 InnerIterMut::Heap(h) => h.size_hint(),
451 }
452 }
453
454 fn last(self) -> Option<(&'a K, &'a mut V)> {
455 match self.inner {
456 InnerIterMut::Inline(i) => i.last().map(|(k, v)| (&*k, v)),
457 InnerIterMut::Heap(h) => h.last(),
458 }
459 }
460}
461
462impl<K, V> FusedIterator for IterMut<'_, K, V> {}
463
464impl<'a, K: 'a, V: 'a> DoubleEndedIterator for IterMut<'a, K, V> {
465 fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> {
466 match &mut self.inner {
467 InnerIterMut::Inline(i) => i.next_back().map(|(k, v)| (&*k, v)),
468 InnerIterMut::Heap(h) => h.next_back(),
469 }
470 }
471}
472
473impl<K, V> ExactSizeIterator for IterMut<'_, K, V> {
474 fn len(&self) -> usize {
475 match &self.inner {
476 InnerIterMut::Inline(i) => i.len(),
477 InnerIterMut::Heap(h) => h.len(),
478 }
479 }
480}
481
482impl<K, V, const ARRAY_SIZE: usize> IntoIterator for SmallBTreeMap<K, V, ARRAY_SIZE> {
483 type Item = (K, V);
484 type IntoIter = IntoIter<K, V, ARRAY_SIZE>;
485
486 fn into_iter(self) -> Self::IntoIter {
487 match self.inner {
488 Inner::Inline(i) => IntoIter {
489 inner: InnerIntoIter::Inline(i.into_iter()),
490 },
491 Inner::Heap(h) => IntoIter {
492 inner: InnerIntoIter::Heap(h.into_iter()),
493 },
494 }
495 }
496}
497
498impl<K, V, const ARRAY_SIZE: usize> Iterator for IntoIter<K, V, ARRAY_SIZE> {
499 type Item = (K, V);
500
501 fn next(&mut self) -> Option<(K, V)> {
502 match &mut self.inner {
503 InnerIntoIter::Inline(i) => i.next(),
504 InnerIntoIter::Heap(h) => h.next(),
505 }
506 }
507
508 fn size_hint(&self) -> (usize, Option<usize>) {
509 match &self.inner {
510 InnerIntoIter::Inline(i) => i.size_hint(),
511 InnerIntoIter::Heap(h) => h.size_hint(),
512 }
513 }
514}
515
516impl<K, V, const ARRAY_SIZE: usize> DoubleEndedIterator for IntoIter<K, V, ARRAY_SIZE> {
517 fn next_back(&mut self) -> Option<(K, V)> {
518 match &mut self.inner {
519 InnerIntoIter::Inline(i) => i.next_back(),
520 InnerIntoIter::Heap(h) => h.next_back(),
521 }
522 }
523}
524
525impl<K, V, const ARRAY_SIZE: usize> ExactSizeIterator for IntoIter<K, V, ARRAY_SIZE> {
526 fn len(&self) -> usize {
527 match &self.inner {
528 InnerIntoIter::Inline(i) => i.len(),
529 InnerIntoIter::Heap(h) => h.len(),
530 }
531 }
532}
533
534impl<K, V, const ARRAY_SIZE: usize> FusedIterator for IntoIter<K, V, ARRAY_SIZE> {}
535
536impl<K: Eq + Ord, V, const ARRAY_SIZE: usize> Extend<(K, V)> for SmallBTreeMap<K, V, ARRAY_SIZE> {
537 fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
538 iter.into_iter().for_each(move |(k, v)| {
539 self.insert(k, v);
540 });
541 }
542}
543
544impl<'a, K: Eq + Ord + Copy, V: Copy, const ARRAY_SIZE: usize> Extend<(&'a K, &'a V)>
545 for SmallBTreeMap<K, V, ARRAY_SIZE>
546{
547 fn extend<I: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: I) {
548 self.extend(iter.into_iter().map(|(&key, &value)| (key, value)));
549 }
550}
551
552impl<K: Hash, V: Hash, const ARRAY_SIZE: usize> Hash for SmallBTreeMap<K, V, ARRAY_SIZE> {
553 fn hash<H: Hasher>(&self, state: &mut H) {
554 state.write_usize(self.len());
557 for elt in self {
558 elt.hash(state);
559 }
560 }
561}
562
563impl<K, V, const ARRAY_SIZE: usize> Default for SmallBTreeMap<K, V, ARRAY_SIZE> {
564 fn default() -> Self {
566 Self::new()
567 }
568}
569
570impl<K: PartialEq + Ord, V: PartialEq, const LHS_SIZE: usize, const RHS_SIZE: usize>
571 PartialEq<SmallBTreeMap<K, V, RHS_SIZE>> for SmallBTreeMap<K, V, LHS_SIZE>
572{
573 fn eq(&self, other: &SmallBTreeMap<K, V, RHS_SIZE>) -> bool {
574 if let (Inner::Heap(lhs), Inner::Heap(rhs)) = (&self.inner, &other.inner) {
575 return lhs == rhs;
576 }
577
578 if self.len() != other.len() {
579 return false;
580 }
581
582 self.iter()
583 .all(|(key, value)| other.get(key).is_some_and(|v| *value == *v))
584 }
585}
586
587impl<K: Eq + Ord, V: Eq, const ARRAY_SIZE: usize> Eq for SmallBTreeMap<K, V, ARRAY_SIZE> {}
588
589impl<K: fmt::Debug, V: fmt::Debug, const ARRAY_SIZE: usize> fmt::Debug
590 for SmallBTreeMap<K, V, ARRAY_SIZE>
591{
592 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
593 f.debug_map().entries(self.iter()).finish()
594 }
595}
596
597impl<K, Q: ?Sized, V, const ARRAY_SIZE: usize> Index<&Q> for SmallBTreeMap<K, V, ARRAY_SIZE>
598where
599 K: Eq + Ord + Borrow<Q>,
600 Q: Eq + Ord,
601{
602 type Output = V;
603
604 fn index(&self, index: &Q) -> &Self::Output {
605 self.get(index).expect("no entry found for key")
606 }
607}
608
609impl<K, Q: ?Sized, V, const ARRAY_SIZE: usize> IndexMut<&Q> for SmallBTreeMap<K, V, ARRAY_SIZE>
610where
611 K: Eq + Ord + Borrow<Q>,
612 Q: Eq + Ord,
613{
614 fn index_mut(&mut self, index: &Q) -> &mut Self::Output {
615 self.get_mut(index).expect("no entry found for key")
616 }
617}
618
619impl<K, V, const ARRAY_SIZE: usize> SmallBTreeMap<K, V, ARRAY_SIZE> {
620 pub fn iter(&self) -> Iter<'_, K, V> {
622 match &self.inner {
623 Inner::Inline(i) => Iter {
624 inner: InnerIter::Inline(i.iter()),
625 },
626 Inner::Heap(h) => Iter {
627 inner: InnerIter::Heap(h.iter()),
628 },
629 }
630 }
631
632 pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
634 match &mut self.inner {
635 Inner::Inline(i) => IterMut {
636 inner: InnerIterMut::Inline(i.iter_mut()),
637 },
638 Inner::Heap(h) => IterMut {
639 inner: InnerIterMut::Heap(h.iter_mut()),
640 },
641 }
642 }
643
644 pub fn len(&self) -> usize {
646 match &self.inner {
647 Inner::Inline(i) => i.len(),
648 Inner::Heap(h) => h.len(),
649 }
650 }
651
652 pub fn is_empty(&self) -> bool {
654 self.len() == 0
655 }
656}