Skip to content

Commit 5ba716b

Browse files
authored
Merge pull request #177 from cuviper/slice
Add dynamically-sized slices of maps and sets
2 parents 1583860 + 8a571c6 commit 5ba716b

File tree

13 files changed

+1081
-18
lines changed

13 files changed

+1081
-18
lines changed

.github/workflows/ci.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
strategy:
1717
matrix:
1818
include:
19-
- rust: 1.56.0 # MSRV
19+
- rust: 1.56.1 # MSRV
2020
features:
2121
- rust: stable
2222
features: serde
@@ -57,7 +57,7 @@ jobs:
5757
strategy:
5858
matrix:
5959
include:
60-
- rust: 1.56.0
60+
- rust: 1.56.1
6161
target: thumbv6m-none-eabi
6262
- rust: stable
6363
target: thumbv6m-none-eabi

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ license = "Apache-2.0 OR MIT"
99
description = "A hash table with consistent order and fast iteration."
1010
keywords = ["hashmap", "no_std"]
1111
categories = ["data-structures", "no-std"]
12-
rust-version = "1.56"
12+
rust-version = "1.56.1"
1313

1414
[lib]
1515
bench = false

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
[![build status](https://github.com/bluss/indexmap/workflows/Continuous%20integration/badge.svg?branch=master)](https://github.com/bluss/indexmap/actions)
44
[![crates.io](https://img.shields.io/crates/v/indexmap.svg)](https://crates.io/crates/indexmap)
55
[![docs](https://docs.rs/indexmap/badge.svg)](https://docs.rs/indexmap)
6-
[![rustc](https://img.shields.io/badge/rust-1.56%2B-orange.svg)](https://img.shields.io/badge/rust-1.56%2B-orange.svg)
6+
[![rustc](https://img.shields.io/badge/rust-1.56.1%2B-orange.svg)](https://img.shields.io/badge/rust-1.56.1%2B-orange.svg)
77

88
A pure-Rust hash table which preserves (in a limited sense) insertion order.
99

RELEASES.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
- 2.0.0 (pending)
22

3-
- **MSRV**: Rust 1.56 or later is now required.
3+
- **MSRV**: Rust 1.56.1 or later is now required.
44

55
- The `hashbrown` dependency has been updated to version 0.12.
66

@@ -19,6 +19,11 @@
1919
- The new `IndexMap::shrink_to` and `IndexSet::shrink_to` methods shrink
2020
the capacity with a lower bound.
2121

22+
- The new `map::Slice<K, V>` and `set::Slice<T>` offer a linear view of maps
23+
and sets, behaving a lot like normal `[(K, V)]` and `[T]` slices. Notably,
24+
comparison traits like `Eq` only consider items in order, rather than hash
25+
lookups, and slices even implement `Hash`.
26+
2227
- 1.8.1
2328

2429
- The new `IndexSet::replace_full` will return the index of the item along

src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
//!
5454
//! ### Rust Version
5555
//!
56-
//! This version of indexmap requires Rust 1.56 or later.
56+
//! This version of indexmap requires Rust 1.56.1 or later.
5757
//!
5858
//! The indexmap 2.x release series will use a carefully considered version
5959
//! upgrade policy, where in a later 2.x version, we will raise the minimum

src/map.rs

+65-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
//! pairs is independent of the hash values of the keys.
33
44
mod core;
5+
mod slice;
56

7+
pub use self::slice::Slice;
68
pub use crate::mutable_keys::MutableKeys;
79

810
#[cfg(feature = "rayon")]
@@ -15,13 +17,14 @@ use ::core::hash::{BuildHasher, Hash, Hasher};
1517
use ::core::iter::FusedIterator;
1618
use ::core::ops::{Index, IndexMut, RangeBounds};
1719
use ::core::slice::{Iter as SliceIter, IterMut as SliceIterMut};
20+
use alloc::boxed::Box;
1821

1922
#[cfg(feature = "std")]
2023
use std::collections::hash_map::RandomState;
2124

2225
use self::core::IndexMapCore;
2326
use crate::equivalent::Equivalent;
24-
use crate::util::third;
27+
use crate::util::{third, try_simplify_range};
2528
use crate::{Bucket, Entries, HashValue};
2629

2730
pub use self::core::{Entry, OccupiedEntry, VacantEntry};
@@ -758,6 +761,27 @@ where
758761
}
759762

760763
impl<K, V, S> IndexMap<K, V, S> {
764+
/// Returns a slice of all the key-value pairs in the map.
765+
///
766+
/// Computes in **O(1)** time.
767+
pub fn as_slice(&self) -> &Slice<K, V> {
768+
Slice::from_slice(self.as_entries())
769+
}
770+
771+
/// Returns a mutable slice of all the key-value pairs in the map.
772+
///
773+
/// Computes in **O(1)** time.
774+
pub fn as_mut_slice(&mut self) -> &mut Slice<K, V> {
775+
Slice::from_mut_slice(self.as_entries_mut())
776+
}
777+
778+
/// Converts into a boxed slice of all the key-value pairs in the map.
779+
///
780+
/// Note that this will drop the inner hash table and any excess capacity.
781+
pub fn into_boxed_slice(self) -> Box<Slice<K, V>> {
782+
Slice::from_boxed(self.into_entries().into_boxed_slice())
783+
}
784+
761785
/// Get a key-value pair by index
762786
///
763787
/// Valid indices are *0 <= index < self.len()*
@@ -776,6 +800,28 @@ impl<K, V, S> IndexMap<K, V, S> {
776800
self.as_entries_mut().get_mut(index).map(Bucket::ref_mut)
777801
}
778802

803+
/// Returns a slice of key-value pairs in the given range of indices.
804+
///
805+
/// Valid indices are *0 <= index < self.len()*
806+
///
807+
/// Computes in **O(1)** time.
808+
pub fn get_range<R: RangeBounds<usize>>(&self, range: R) -> Option<&Slice<K, V>> {
809+
let entries = self.as_entries();
810+
let range = try_simplify_range(range, entries.len())?;
811+
entries.get(range).map(Slice::from_slice)
812+
}
813+
814+
/// Returns a mutable slice of key-value pairs in the given range of indices.
815+
///
816+
/// Valid indices are *0 <= index < self.len()*
817+
///
818+
/// Computes in **O(1)** time.
819+
pub fn get_range_mut<R: RangeBounds<usize>>(&mut self, range: R) -> Option<&mut Slice<K, V>> {
820+
let entries = self.as_entries_mut();
821+
let range = try_simplify_range(range, entries.len())?;
822+
entries.get_mut(range).map(Slice::from_mut_slice)
823+
}
824+
779825
/// Get the first key-value pair
780826
///
781827
/// Computes in **O(1)** time.
@@ -846,7 +892,7 @@ impl<K, V, S> IndexMap<K, V, S> {
846892
/// [`keys`]: struct.IndexMap.html#method.keys
847893
/// [`IndexMap`]: struct.IndexMap.html
848894
pub struct Keys<'a, K, V> {
849-
pub(crate) iter: SliceIter<'a, Bucket<K, V>>,
895+
iter: SliceIter<'a, Bucket<K, V>>,
850896
}
851897

852898
impl<'a, K, V> Iterator for Keys<'a, K, V> {
@@ -1045,6 +1091,13 @@ pub struct Iter<'a, K, V> {
10451091
iter: SliceIter<'a, Bucket<K, V>>,
10461092
}
10471093

1094+
impl<'a, K, V> Iter<'a, K, V> {
1095+
/// Returns a slice of the remaining entries in the iterator.
1096+
pub fn as_slice(&self) -> &'a Slice<K, V> {
1097+
Slice::from_slice(self.iter.as_slice())
1098+
}
1099+
}
1100+
10481101
impl<'a, K, V> Iterator for Iter<'a, K, V> {
10491102
type Item = (&'a K, &'a V);
10501103

@@ -1089,6 +1142,15 @@ pub struct IterMut<'a, K, V> {
10891142
iter: SliceIterMut<'a, Bucket<K, V>>,
10901143
}
10911144

1145+
impl<'a, K, V> IterMut<'a, K, V> {
1146+
/// Returns a slice of the remaining entries in the iterator.
1147+
///
1148+
/// To avoid creating `&mut` references that alias, this is forced to consume the iterator.
1149+
pub fn into_slice(self) -> &'a mut Slice<K, V> {
1150+
Slice::from_mut_slice(self.iter.into_slice())
1151+
}
1152+
}
1153+
10921154
impl<'a, K, V> Iterator for IterMut<'a, K, V> {
10931155
type Item = (&'a K, &'a mut V);
10941156

@@ -1122,7 +1184,7 @@ impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IterMut<'_, K, V> {
11221184
/// [`into_iter`]: struct.IndexMap.html#method.into_iter
11231185
/// [`IndexMap`]: struct.IndexMap.html
11241186
pub struct IntoIter<K, V> {
1125-
pub(crate) iter: vec::IntoIter<Bucket<K, V>>,
1187+
iter: vec::IntoIter<Bucket<K, V>>,
11261188
}
11271189

11281190
impl<K, V> Iterator for IntoIter<K, V> {

0 commit comments

Comments
 (0)