Skip to content

Commit 7f9af49

Browse files
committed
Add get_range and get_range_mut
1 parent 45852b7 commit 7f9af49

File tree

3 files changed

+77
-4
lines changed

3 files changed

+77
-4
lines changed

src/map/slice.rs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use super::{Bucket, Entries, IndexMap, Iter, IterMut, Keys, Values, ValuesMut};
2-
use crate::util::simplify_range;
2+
use crate::util::{simplify_range, try_simplify_range};
33

44
use core::cmp::Ordering;
55
use core::fmt;
66
use core::hash::{Hash, Hasher};
7-
use core::ops::{self, Bound, Index, IndexMut};
7+
use core::ops::{self, Bound, Index, IndexMut, RangeBounds};
88

99
/// A dynamically-sized slice of key-value pairs in an `IndexMap`.
1010
///
@@ -43,6 +43,24 @@ impl<K, V, S> IndexMap<K, V, S> {
4343
pub fn as_mut_slice(&mut self) -> &mut Slice<K, V> {
4444
Slice::from_mut_slice(self.as_entries_mut())
4545
}
46+
47+
/// Returns a slice of entries in the given range of indices.
48+
///
49+
/// Valid indices are *0 <= index < self.len()*
50+
pub fn get_range<R: RangeBounds<usize>>(&self, range: R) -> Option<&Slice<K, V>> {
51+
let entries = self.as_entries();
52+
let range = try_simplify_range(range, entries.len())?;
53+
entries.get(range).map(Slice::from_slice)
54+
}
55+
56+
/// Returns a mutable slice of entries in the given range of indices.
57+
///
58+
/// Valid indices are *0 <= index < self.len()*
59+
pub fn get_range_mut<R: RangeBounds<usize>>(&mut self, range: R) -> Option<&mut Slice<K, V>> {
60+
let entries = self.as_entries_mut();
61+
let range = try_simplify_range(range, entries.len())?;
62+
entries.get_mut(range).map(Slice::from_mut_slice)
63+
}
4664
}
4765

4866
impl<'a, K, V> Iter<'a, K, V> {
@@ -90,6 +108,22 @@ impl<K, V> Slice<K, V> {
90108
self.entries.get_mut(index).map(Bucket::ref_mut)
91109
}
92110

111+
/// Returns a slice of key-value pairs in the given range of indices.
112+
///
113+
/// Valid indices are *0 <= index < self.len()*
114+
pub fn get_range<R: RangeBounds<usize>>(&self, range: R) -> Option<&Self> {
115+
let range = try_simplify_range(range, self.entries.len())?;
116+
self.entries.get(range).map(Slice::from_slice)
117+
}
118+
119+
/// Returns a mutable slice of key-value pairs in the given range of indices.
120+
///
121+
/// Valid indices are *0 <= index < self.len()*
122+
pub fn get_range_mut<R: RangeBounds<usize>>(&mut self, range: R) -> Option<&mut Self> {
123+
let range = try_simplify_range(range, self.entries.len())?;
124+
self.entries.get_mut(range).map(Slice::from_mut_slice)
125+
}
126+
93127
/// Get the first key-value pair.
94128
pub fn first(&self) -> Option<(&K, &V)> {
95129
self.entries.first().map(Bucket::refs)

src/set/slice.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use super::{Bucket, Entries, IndexSet, Iter};
2-
use crate::util::simplify_range;
2+
use crate::util::{simplify_range, try_simplify_range};
33

44
use core::cmp::Ordering;
55
use core::fmt;
66
use core::hash::{Hash, Hasher};
7-
use core::ops::{self, Bound, Index};
7+
use core::ops::{self, Bound, Index, RangeBounds};
88

99
/// A dynamically-sized slice of values in an `IndexSet`.
1010
///
@@ -32,6 +32,15 @@ impl<T, S> IndexSet<T, S> {
3232
pub fn as_slice(&self) -> &Slice<T> {
3333
Slice::from_slice(self.as_entries())
3434
}
35+
36+
/// Returns a slice of values in the given range of indices.
37+
///
38+
/// Valid indices are *0 <= index < self.len()*
39+
pub fn get_range<R: RangeBounds<usize>>(&self, range: R) -> Option<&Slice<T>> {
40+
let entries = self.as_entries();
41+
let range = try_simplify_range(range, entries.len())?;
42+
entries.get(range).map(Slice::from_slice)
43+
}
3544
}
3645

3746
impl<'a, T> Iter<'a, T> {
@@ -59,6 +68,14 @@ impl<T> Slice<T> {
5968
self.entries.get(index).map(Bucket::key_ref)
6069
}
6170

71+
/// Returns a slice of values in the given range of indices.
72+
///
73+
/// Valid indices are *0 <= index < self.len()*
74+
pub fn get_range<R: RangeBounds<usize>>(&self, range: R) -> Option<&Self> {
75+
let range = try_simplify_range(range, self.entries.len())?;
76+
self.entries.get(range).map(Self::from_slice)
77+
}
78+
6279
/// Get the first value.
6380
pub fn first(&self) -> Option<&T> {
6481
self.entries.first().map(Bucket::key_ref)

src/util.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,25 @@ where
2929
}
3030
start..end
3131
}
32+
33+
pub(crate) fn try_simplify_range<R>(range: R, len: usize) -> Option<Range<usize>>
34+
where
35+
R: RangeBounds<usize>,
36+
{
37+
let start = match range.start_bound() {
38+
Bound::Unbounded => 0,
39+
Bound::Included(&i) if i <= len => i,
40+
Bound::Excluded(&i) if i < len => i + 1,
41+
_ => return None,
42+
};
43+
let end = match range.end_bound() {
44+
Bound::Unbounded => len,
45+
Bound::Excluded(&i) if i <= len => i,
46+
Bound::Included(&i) if i < len => i + 1,
47+
_ => return None,
48+
};
49+
if start > end {
50+
return None;
51+
}
52+
Some(start..end)
53+
}

0 commit comments

Comments
 (0)