Skip to content

Commit bb225db

Browse files
authored
Merge pull request #495 from Nitrokey/binary-heap-view-dedup
BinaryHeap: implement BinaryHeapView on top of #486
2 parents 7a321db + 7b28def commit bb225db

File tree

3 files changed

+125
-28
lines changed

3 files changed

+125
-28
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2626
- Implemented `DoubleEndedIterator` for `OldestOrdered`.
2727
- Added std `Entry` methods to indexmap `Entry`.
2828
- Added `StringView`, the `!Sized` version of `String`.
29+
- Added `BinaryHeapView`, the `!Sized` version of `BinaryHeap`.
2930
- Added `MpMcQueueView`, the `!Sized` version of `MpMcQueue`.
3031
- Added `LinearMapView`, the `!Sized` version of `LinearMap`.
3132
- Added `HistoryBufferView`, the `!Sized` version of `HistoryBuffer`.

src/binary_heap.rs

+113-23
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ use core::{
1717
ptr, slice,
1818
};
1919

20-
use crate::vec::Vec;
20+
use crate::{
21+
storage::{OwnedStorage, Storage, ViewStorage},
22+
vec::{Vec, VecInner},
23+
};
2124

2225
/// Min-heap
2326
pub enum Min {}
@@ -51,6 +54,15 @@ mod private {
5154
impl private::Sealed for Max {}
5255
impl private::Sealed for Min {}
5356

57+
/// Base struct for [`BinaryHeap`] and [`BinaryHeapView`], generic over the [`Storage`].
58+
///
59+
/// In most cases you should use [`BinaryHeap`] or [`BinaryHeapView`] directly. Only use this
60+
/// struct if you want to write code that's generic over both.
61+
pub struct BinaryHeapInner<T, K, S: Storage> {
62+
pub(crate) _kind: PhantomData<K>,
63+
pub(crate) data: VecInner<T, S>,
64+
}
65+
5466
/// A priority queue implemented with a binary heap.
5567
///
5668
/// This can be either a min-heap or a max-heap.
@@ -97,10 +109,56 @@ impl private::Sealed for Min {}
97109
/// // The heap should now be empty.
98110
/// assert!(heap.is_empty())
99111
/// ```
100-
pub struct BinaryHeap<T, K, const N: usize> {
101-
pub(crate) _kind: PhantomData<K>,
102-
pub(crate) data: Vec<T, N>,
103-
}
112+
pub type BinaryHeap<T, K, const N: usize> = BinaryHeapInner<T, K, OwnedStorage<N>>;
113+
114+
/// A priority queue implemented with a binary heap.
115+
///
116+
/// This can be either a min-heap or a max-heap.
117+
///
118+
/// It is a logic error for an item to be modified in such a way that the item's ordering relative
119+
/// to any other item, as determined by the `Ord` trait, changes while it is in the heap. This is
120+
/// normally only possible through `Cell`, `RefCell`, global state, I/O, or unsafe code.
121+
///
122+
/// ```
123+
/// use heapless::binary_heap::{BinaryHeap, BinaryHeapView, Max};
124+
///
125+
/// let mut heap_buffer: BinaryHeap<_, Max, 8> = BinaryHeap::new();
126+
/// let heap: &mut BinaryHeapView<_, Max> = &mut heap_buffer;
127+
///
128+
/// // We can use peek to look at the next item in the heap. In this case,
129+
/// // there's no items in there yet so we get None.
130+
/// assert_eq!(heap.peek(), None);
131+
///
132+
/// // Let's add some scores...
133+
/// heap.push(1).unwrap();
134+
/// heap.push(5).unwrap();
135+
/// heap.push(2).unwrap();
136+
///
137+
/// // Now peek shows the most important item in the heap.
138+
/// assert_eq!(heap.peek(), Some(&5));
139+
///
140+
/// // We can check the length of a heap.
141+
/// assert_eq!(heap.len(), 3);
142+
///
143+
/// // We can iterate over the items in the heap, although they are returned in
144+
/// // a random order.
145+
/// for x in &*heap {
146+
/// println!("{}", x);
147+
/// }
148+
///
149+
/// // If we instead pop these scores, they should come back in order.
150+
/// assert_eq!(heap.pop(), Some(5));
151+
/// assert_eq!(heap.pop(), Some(2));
152+
/// assert_eq!(heap.pop(), Some(1));
153+
/// assert_eq!(heap.pop(), None);
154+
///
155+
/// // We can clear the heap of any remaining items.
156+
/// heap.clear();
157+
///
158+
/// // The heap should now be empty.
159+
/// assert!(heap.is_empty())
160+
/// ```
161+
pub type BinaryHeapView<T, K> = BinaryHeapInner<T, K, ViewStorage>;
104162

105163
impl<T, K, const N: usize> BinaryHeap<T, K, N> {
106164
/* Constructors */
@@ -124,7 +182,23 @@ impl<T, K, const N: usize> BinaryHeap<T, K, N> {
124182
}
125183
}
126184

127-
impl<T, K, const N: usize> BinaryHeap<T, K, N>
185+
impl<T, K, const N: usize> BinaryHeap<T, K, N> {
186+
/// Returns the underlying `Vec<T,N>`. Order is arbitrary and time is *O*(1).
187+
pub fn into_vec(self) -> Vec<T, N> {
188+
self.data
189+
}
190+
191+
/// Get a reference to the `BinaryHeap`, erasing the `N` const-generic.
192+
pub fn as_view(&self) -> &BinaryHeapView<T, K> {
193+
self
194+
}
195+
/// Get a mutable reference to the `BinaryHeap`, erasing the `N` const-generic.
196+
pub fn as_mut_view(&mut self) -> &mut BinaryHeapView<T, K> {
197+
self
198+
}
199+
}
200+
201+
impl<T, K, S: Storage> BinaryHeapInner<T, K, S>
128202
where
129203
T: Ord,
130204
K: Kind,
@@ -260,11 +334,11 @@ where
260334
///
261335
/// assert_eq!(heap.peek(), Some(&2));
262336
/// ```
263-
pub fn peek_mut(&mut self) -> Option<PeekMut<'_, T, K, N>> {
337+
pub fn peek_mut(&mut self) -> Option<PeekMutInner<'_, T, K, S>> {
264338
if self.is_empty() {
265339
None
266340
} else {
267-
Some(PeekMut {
341+
Some(PeekMutInner {
268342
heap: self,
269343
sift: true,
270344
})
@@ -336,11 +410,6 @@ where
336410
self.sift_up(0, old_len);
337411
}
338412

339-
/// Returns the underlying `Vec<T,N>`. Order is arbitrary and time is *O*(1).
340-
pub fn into_vec(self) -> Vec<T, N> {
341-
self.data
342-
}
343-
344413
/* Private API */
345414
fn sift_down_to_bottom(&mut self, mut pos: usize) {
346415
let end = self.len();
@@ -444,21 +513,37 @@ impl<'a, T> Hole<'a, T> {
444513
/// Structure wrapping a mutable reference to the greatest item on a
445514
/// `BinaryHeap`.
446515
///
447-
/// This `struct` is created by [`BinaryHeap::peek_mut`].
516+
/// This `struct` is created by [`BinaryHeapInner::peek_mut`].
448517
/// See its documentation for more.
449-
pub struct PeekMut<'a, T, K, const N: usize>
518+
pub struct PeekMutInner<'a, T, K, S>
450519
where
451520
T: Ord,
452521
K: Kind,
522+
S: Storage,
453523
{
454-
heap: &'a mut BinaryHeap<T, K, N>,
524+
heap: &'a mut BinaryHeapInner<T, K, S>,
455525
sift: bool,
456526
}
457527

458-
impl<T, K, const N: usize> Drop for PeekMut<'_, T, K, N>
528+
/// Structure wrapping a mutable reference to the greatest item on a
529+
/// `BinaryHeap`.
530+
///
531+
/// This `struct` is created by [`BinaryHeap::peek_mut`].
532+
/// See its documentation for more.
533+
pub type PeekMut<'a, T, K, const N: usize> = PeekMutInner<'a, T, K, OwnedStorage<N>>;
534+
535+
/// Structure wrapping a mutable reference to the greatest item on a
536+
/// `BinaryHeap`.
537+
///
538+
/// This `struct` is created by [`BinaryHeapView::peek_mut`].
539+
/// See its documentation for more.
540+
pub type PeekMutView<'a, T, K> = PeekMutInner<'a, T, K, ViewStorage>;
541+
542+
impl<T, K, S> Drop for PeekMutInner<'_, T, K, S>
459543
where
460544
T: Ord,
461545
K: Kind,
546+
S: Storage,
462547
{
463548
fn drop(&mut self) {
464549
if self.sift {
@@ -467,10 +552,11 @@ where
467552
}
468553
}
469554

470-
impl<T, K, const N: usize> Deref for PeekMut<'_, T, K, N>
555+
impl<T, K, S> Deref for PeekMutInner<'_, T, K, S>
471556
where
472557
T: Ord,
473558
K: Kind,
559+
S: Storage,
474560
{
475561
type Target = T;
476562
fn deref(&self) -> &T {
@@ -480,10 +566,11 @@ where
480566
}
481567
}
482568

483-
impl<T, K, const N: usize> DerefMut for PeekMut<'_, T, K, N>
569+
impl<T, K, S> DerefMut for PeekMutInner<'_, T, K, S>
484570
where
485571
T: Ord,
486572
K: Kind,
573+
S: Storage,
487574
{
488575
fn deref_mut(&mut self) -> &mut T {
489576
debug_assert!(!self.heap.is_empty());
@@ -492,13 +579,14 @@ where
492579
}
493580
}
494581

495-
impl<'a, T, K, const N: usize> PeekMut<'a, T, K, N>
582+
impl<'a, T, K, S> PeekMutInner<'a, T, K, S>
496583
where
497584
T: Ord,
498585
K: Kind,
586+
S: Storage,
499587
{
500588
/// Removes the peeked value from the heap and returns it.
501-
pub fn pop(mut this: PeekMut<'a, T, K, N>) -> T {
589+
pub fn pop(mut this: PeekMutInner<'a, T, K, S>) -> T {
502590
let value = this.heap.pop().unwrap();
503591
this.sift = false;
504592
value
@@ -539,20 +627,22 @@ where
539627
}
540628
}
541629

542-
impl<T, K, const N: usize> fmt::Debug for BinaryHeap<T, K, N>
630+
impl<T, K, S> fmt::Debug for BinaryHeapInner<T, K, S>
543631
where
544632
K: Kind,
545633
T: Ord + fmt::Debug,
634+
S: Storage,
546635
{
547636
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
548637
f.debug_list().entries(self.iter()).finish()
549638
}
550639
}
551640

552-
impl<'a, T, K, const N: usize> IntoIterator for &'a BinaryHeap<T, K, N>
641+
impl<'a, T, K, S> IntoIterator for &'a BinaryHeapInner<T, K, S>
553642
where
554643
K: Kind,
555644
T: Ord,
645+
S: Storage,
556646
{
557647
type Item = &'a T;
558648
type IntoIter = slice::Iter<'a, T>;

src/ser.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,27 @@
11
use core::hash::{BuildHasher, Hash};
22

33
use crate::{
4-
binary_heap::Kind as BinaryHeapKind, histbuf::HistoryBufferInner, linear_map::LinearMapInner,
5-
storage::Storage, string::StringInner, vec::VecInner, BinaryHeap, Deque, IndexMap, IndexSet,
4+
binary_heap::{BinaryHeapInner, Kind as BinaryHeapKind},
5+
histbuf::HistoryBufferInner,
6+
linear_map::LinearMapInner,
7+
storage::Storage,
8+
string::StringInner,
9+
vec::VecInner,
10+
Deque, IndexMap, IndexSet,
611
};
712
use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
813

914
// Sequential containers
1015

11-
impl<T, KIND, const N: usize> Serialize for BinaryHeap<T, KIND, N>
16+
impl<T, KIND, S> Serialize for BinaryHeapInner<T, KIND, S>
1217
where
1318
T: Ord + Serialize,
1419
KIND: BinaryHeapKind,
20+
S: Storage,
1521
{
16-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
22+
fn serialize<SER>(&self, serializer: SER) -> Result<SER::Ok, SER::Error>
1723
where
18-
S: Serializer,
24+
SER: Serializer,
1925
{
2026
let mut seq = serializer.serialize_seq(Some(self.len()))?;
2127
for element in self {

0 commit comments

Comments
 (0)