Skip to content

Commit 8c49292

Browse files
committed
Add boxed slices, including owned iterators
1 parent 9f2b14d commit 8c49292

File tree

6 files changed

+122
-8
lines changed

6 files changed

+122
-8
lines changed

src/map.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use ::core::hash::{BuildHasher, Hash, Hasher};
1717
use ::core::iter::FusedIterator;
1818
use ::core::ops::{Index, IndexMut, RangeBounds};
1919
use ::core::slice::{Iter as SliceIter, IterMut as SliceIterMut};
20+
use alloc::boxed::Box;
2021

2122
#[cfg(feature = "std")]
2223
use std::collections::hash_map::RandomState;
@@ -774,6 +775,13 @@ impl<K, V, S> IndexMap<K, V, S> {
774775
Slice::from_mut_slice(self.as_entries_mut())
775776
}
776777

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+
777785
/// Get a key-value pair by index
778786
///
779787
/// Valid indices are *0 <= index < self.len()*

src/map/slice.rs

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1-
use super::{Bucket, Entries, IndexMap, Iter, IterMut, Keys, Values, ValuesMut};
1+
use super::{
2+
Bucket, Entries, IndexMap, IntoIter, IntoKeys, IntoValues, Iter, IterMut, Keys, Values,
3+
ValuesMut,
4+
};
25
use crate::util::try_simplify_range;
36

7+
use alloc::boxed::Box;
8+
use alloc::vec::Vec;
49
use core::cmp::Ordering;
510
use core::fmt;
611
use core::hash::{Hash, Hasher};
@@ -18,22 +23,32 @@ pub struct Slice<K, V> {
1823
pub(crate) entries: [Bucket<K, V>],
1924
}
2025

26+
// SAFETY: `Slice<K, V>` is a transparent wrapper around `[Bucket<K, V>]`,
27+
// and reference lifetimes are bound together in function signatures.
2128
#[allow(unsafe_code)]
2229
impl<K, V> Slice<K, V> {
2330
pub(super) fn from_slice(entries: &[Bucket<K, V>]) -> &Self {
24-
// SAFETY: `Slice<K, V>` is a transparent wrapper around `[Bucket<K, V>]`,
25-
// and the lifetimes are bound together by this function's signature.
2631
unsafe { &*(entries as *const [Bucket<K, V>] as *const Self) }
2732
}
2833

2934
pub(super) fn from_mut_slice(entries: &mut [Bucket<K, V>]) -> &mut Self {
30-
// SAFETY: `Slice<K, V>` is a transparent wrapper around `[Bucket<K, V>]`,
31-
// and the lifetimes are bound together by this function's signature.
3235
unsafe { &mut *(entries as *mut [Bucket<K, V>] as *mut Self) }
3336
}
37+
38+
pub(super) fn from_boxed(entries: Box<[Bucket<K, V>]>) -> Box<Self> {
39+
unsafe { Box::from_raw(Box::into_raw(entries) as *mut Self) }
40+
}
41+
42+
fn into_boxed(self: Box<Self>) -> Box<[Bucket<K, V>]> {
43+
unsafe { Box::from_raw(Box::into_raw(self) as *mut [Bucket<K, V>]) }
44+
}
3445
}
3546

3647
impl<K, V> Slice<K, V> {
48+
pub(crate) fn into_entries(self: Box<Self>) -> Vec<Bucket<K, V>> {
49+
self.into_boxed().into_vec()
50+
}
51+
3752
/// Return the number of key-value pairs in the map slice.
3853
#[inline]
3954
pub fn len(&self) -> usize {
@@ -173,6 +188,13 @@ impl<K, V> Slice<K, V> {
173188
}
174189
}
175190

191+
/// Return an owning iterator over the keys of the map slice.
192+
pub fn into_keys(self: Box<Self>) -> IntoKeys<K, V> {
193+
IntoKeys {
194+
iter: self.into_entries().into_iter(),
195+
}
196+
}
197+
176198
/// Return an iterator over the values of the map slice.
177199
pub fn values(&self) -> Values<'_, K, V> {
178200
Values {
@@ -186,6 +208,13 @@ impl<K, V> Slice<K, V> {
186208
iter: self.entries.iter_mut(),
187209
}
188210
}
211+
212+
/// Return an owning iterator over the values of the map slice.
213+
pub fn into_values(self: Box<Self>) -> IntoValues<K, V> {
214+
IntoValues {
215+
iter: self.into_entries().into_iter(),
216+
}
217+
}
189218
}
190219

191220
impl<'a, K, V> IntoIterator for &'a Slice<K, V> {
@@ -206,6 +235,17 @@ impl<'a, K, V> IntoIterator for &'a mut Slice<K, V> {
206235
}
207236
}
208237

238+
impl<K, V> IntoIterator for Box<Slice<K, V>> {
239+
type IntoIter = IntoIter<K, V>;
240+
type Item = (K, V);
241+
242+
fn into_iter(self) -> Self::IntoIter {
243+
IntoIter {
244+
iter: self.into_entries().into_iter(),
245+
}
246+
}
247+
}
248+
209249
impl<K, V> Default for &'_ Slice<K, V> {
210250
fn default() -> Self {
211251
Slice::from_slice(&[])

src/rayon/map.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rayon::iter::plumbing::{Consumer, ProducerCallback, UnindexedConsumer};
1010
use rayon::prelude::*;
1111

1212
use crate::vec::Vec;
13+
use alloc::boxed::Box;
1314
use core::cmp::Ordering;
1415
use core::fmt;
1516
use core::hash::{BuildHasher, Hash};
@@ -36,6 +37,22 @@ where
3637
}
3738
}
3839

40+
/// Requires crate feature `"rayon"`.
41+
impl<K, V> IntoParallelIterator for Box<Slice<K, V>>
42+
where
43+
K: Send,
44+
V: Send,
45+
{
46+
type Item = (K, V);
47+
type Iter = IntoParIter<K, V>;
48+
49+
fn into_par_iter(self) -> Self::Iter {
50+
IntoParIter {
51+
entries: self.into_entries(),
52+
}
53+
}
54+
}
55+
3956
/// A parallel owning iterator over the entries of a `IndexMap`.
4057
///
4158
/// This `struct` is created by the [`into_par_iter`] method on [`IndexMap`]

src/rayon/set.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rayon::iter::plumbing::{Consumer, ProducerCallback, UnindexedConsumer};
1010
use rayon::prelude::*;
1111

1212
use crate::vec::Vec;
13+
use alloc::boxed::Box;
1314
use core::cmp::Ordering;
1415
use core::fmt;
1516
use core::hash::{BuildHasher, Hash};
@@ -36,6 +37,21 @@ where
3637
}
3738
}
3839

40+
/// Requires crate feature `"rayon"`.
41+
impl<T> IntoParallelIterator for Box<Slice<T>>
42+
where
43+
T: Send,
44+
{
45+
type Item = T;
46+
type Iter = IntoParIter<T>;
47+
48+
fn into_par_iter(self) -> Self::Iter {
49+
IntoParIter {
50+
entries: self.into_entries(),
51+
}
52+
}
53+
}
54+
3955
/// A parallel owning iterator over the items of a `IndexSet`.
4056
///
4157
/// This `struct` is created by the [`into_par_iter`] method on [`IndexSet`]

src/set.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use std::collections::hash_map::RandomState;
1212

1313
use crate::util::try_simplify_range;
1414
use crate::vec::{self, Vec};
15+
use alloc::boxed::Box;
1516
use core::cmp::Ordering;
1617
use core::fmt;
1718
use core::hash::{BuildHasher, Hash};
@@ -663,6 +664,13 @@ impl<T, S> IndexSet<T, S> {
663664
Slice::from_slice(self.as_entries())
664665
}
665666

667+
/// Converts into a boxed slice of all the values in the set.
668+
///
669+
/// Note that this will drop the inner hash table and any excess capacity.
670+
pub fn into_boxed_slice(self) -> Box<Slice<T>> {
671+
Slice::from_boxed(self.into_entries().into_boxed_slice())
672+
}
673+
666674
/// Get a value by index
667675
///
668676
/// Valid indices are *0 <= index < self.len()*

src/set/slice.rs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
use super::{Bucket, Entries, IndexSet, Iter};
1+
use super::{Bucket, Entries, IndexSet, IntoIter, Iter};
22
use crate::util::try_simplify_range;
33

4+
use alloc::boxed::Box;
5+
use alloc::vec::Vec;
46
use core::cmp::Ordering;
57
use core::fmt;
68
use core::hash::{Hash, Hasher};
@@ -18,16 +20,28 @@ pub struct Slice<T> {
1820
pub(crate) entries: [Bucket<T>],
1921
}
2022

23+
// SAFETY: `Slice<T>` is a transparent wrapper around `[Bucket<T>]`,
24+
// and reference lifetimes are bound together in function signatures.
2125
#[allow(unsafe_code)]
2226
impl<T> Slice<T> {
2327
pub(super) fn from_slice(entries: &[Bucket<T>]) -> &Self {
24-
// SAFETY: `Slice<T>` is a transparent wrapper around `[Bucket<T>]`,
25-
// and the lifetimes are bound together by this function's signature.
2628
unsafe { &*(entries as *const [Bucket<T>] as *const Self) }
2729
}
30+
31+
pub(super) fn from_boxed(entries: Box<[Bucket<T>]>) -> Box<Self> {
32+
unsafe { Box::from_raw(Box::into_raw(entries) as *mut Self) }
33+
}
34+
35+
fn into_boxed(self: Box<Self>) -> Box<[Bucket<T>]> {
36+
unsafe { Box::from_raw(Box::into_raw(self) as *mut [Bucket<T>]) }
37+
}
2838
}
2939

3040
impl<T> Slice<T> {
41+
pub(crate) fn into_entries(self: Box<Self>) -> Vec<Bucket<T>> {
42+
self.into_boxed().into_vec()
43+
}
44+
3145
/// Return the number of elements in the set slice.
3246
pub fn len(&self) -> usize {
3347
self.entries.len()
@@ -108,6 +122,17 @@ impl<'a, T> IntoIterator for &'a Slice<T> {
108122
}
109123
}
110124

125+
impl<T> IntoIterator for Box<Slice<T>> {
126+
type IntoIter = IntoIter<T>;
127+
type Item = T;
128+
129+
fn into_iter(self) -> Self::IntoIter {
130+
IntoIter {
131+
iter: self.into_entries().into_iter(),
132+
}
133+
}
134+
}
135+
111136
impl<T> Default for &'_ Slice<T> {
112137
fn default() -> Self {
113138
Slice::from_slice(&[])

0 commit comments

Comments
 (0)