Skip to content

Commit e8aa152

Browse files
bors[bot]korken89
andauthored
Merge #117
117: Added peek_mut for the binary heap r=japaric a=korken89 As discussed in #109, please have a look and lets bike-shed the API. Co-authored-by: Emil Fresk <[email protected]>
2 parents 03b890f + fde6afe commit e8aa152

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed

src/binary_heap.rs

+143
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use core::{
1212
fmt,
1313
marker::PhantomData,
1414
mem::{self, ManuallyDrop},
15+
ops::{Deref, DerefMut},
1516
ptr, slice,
1617
};
1718

@@ -226,6 +227,44 @@ where
226227
self.0.data.as_slice().get(0)
227228
}
228229

230+
/// Returns a mutable reference to the greatest item in the binary heap, or
231+
/// `None` if it is empty.
232+
///
233+
/// Note: If the `PeekMut` value is leaked, the heap may be in an
234+
/// inconsistent state.
235+
///
236+
/// # Examples
237+
///
238+
/// Basic usage:
239+
///
240+
/// ```
241+
/// use heapless::binary_heap::{BinaryHeap, Max};
242+
/// use heapless::consts::*;
243+
///
244+
/// let mut heap: BinaryHeap<_, U8, Max> = BinaryHeap::new();
245+
/// assert!(heap.peek_mut().is_none());
246+
///
247+
/// heap.push(1);
248+
/// heap.push(5);
249+
/// heap.push(2);
250+
/// {
251+
/// let mut val = heap.peek_mut().unwrap();
252+
/// *val = 0;
253+
/// }
254+
///
255+
/// assert_eq!(heap.peek(), Some(&2));
256+
/// ```
257+
pub fn peek_mut(&mut self) -> Option<PeekMut<'_, T, N, K>> {
258+
if self.is_empty() {
259+
None
260+
} else {
261+
Some(PeekMut {
262+
heap: self,
263+
sift: true,
264+
})
265+
}
266+
}
267+
229268
/// Removes the *top* (greatest if max-heap, smallest if min-heap) item from the binary heap and
230269
/// returns it, or None if it is empty.
231270
///
@@ -390,6 +429,78 @@ impl<'a, T> Hole<'a, T> {
390429
}
391430
}
392431

432+
/// Structure wrapping a mutable reference to the greatest item on a
433+
/// `BinaryHeap`.
434+
///
435+
/// This `struct` is created by the [`peek_mut`] method on [`BinaryHeap`]. See
436+
/// its documentation for more.
437+
///
438+
/// [`peek_mut`]: struct.BinaryHeap.html#method.peek_mut
439+
/// [`BinaryHeap`]: struct.BinaryHeap.html
440+
pub struct PeekMut<'a, T, N, K>
441+
where
442+
T: Ord,
443+
N: ArrayLength<T>,
444+
K: Kind,
445+
{
446+
heap: &'a mut BinaryHeap<T, N, K>,
447+
sift: bool,
448+
}
449+
450+
impl<T, N, K> Drop for PeekMut<'_, T, N, K>
451+
where
452+
T: Ord,
453+
N: ArrayLength<T>,
454+
K: Kind,
455+
{
456+
fn drop(&mut self) {
457+
if self.sift {
458+
self.heap.sift_down_to_bottom(0);
459+
}
460+
}
461+
}
462+
463+
impl<T, N, K> Deref for PeekMut<'_, T, N, K>
464+
where
465+
T: Ord,
466+
N: ArrayLength<T>,
467+
K: Kind,
468+
{
469+
type Target = T;
470+
fn deref(&self) -> &T {
471+
debug_assert!(!self.heap.is_empty());
472+
// SAFE: PeekMut is only instantiated for non-empty heaps
473+
unsafe { self.heap.0.data.as_slice().get_unchecked(0) }
474+
}
475+
}
476+
477+
impl<T, N, K> DerefMut for PeekMut<'_, T, N, K>
478+
where
479+
T: Ord,
480+
N: ArrayLength<T>,
481+
K: Kind,
482+
{
483+
fn deref_mut(&mut self) -> &mut T {
484+
debug_assert!(!self.heap.is_empty());
485+
// SAFE: PeekMut is only instantiated for non-empty heaps
486+
unsafe { self.heap.0.data.as_mut_slice().get_unchecked_mut(0) }
487+
}
488+
}
489+
490+
impl<'a, T, N, K> PeekMut<'a, T, N, K>
491+
where
492+
T: Ord,
493+
N: ArrayLength<T>,
494+
K: Kind,
495+
{
496+
/// Removes the peeked value from the heap and returns it.
497+
pub fn pop(mut this: PeekMut<'a, T, N, K>) -> T {
498+
let value = this.heap.pop().unwrap();
499+
this.sift = false;
500+
value
501+
}
502+
}
503+
393504
impl<'a, T> Drop for Hole<'a, T> {
394505
#[inline]
395506
fn drop(&mut self) {
@@ -510,6 +621,22 @@ mod tests {
510621
assert_eq!(heap.pop(), Some(36));
511622
assert_eq!(heap.pop(), Some(100));
512623
assert_eq!(heap.pop(), None);
624+
625+
assert!(heap.peek_mut().is_none());
626+
627+
heap.push(1).unwrap();
628+
heap.push(2).unwrap();
629+
heap.push(10).unwrap();
630+
631+
{
632+
let mut val = heap.peek_mut().unwrap();
633+
*val = 7;
634+
}
635+
636+
assert_eq!(heap.pop(), Some(2));
637+
assert_eq!(heap.pop(), Some(7));
638+
assert_eq!(heap.pop(), Some(10));
639+
assert_eq!(heap.pop(), None);
513640
}
514641

515642
#[test]
@@ -546,5 +673,21 @@ mod tests {
546673
assert_eq!(heap.pop(), Some(2));
547674
assert_eq!(heap.pop(), Some(1));
548675
assert_eq!(heap.pop(), None);
676+
677+
assert!(heap.peek_mut().is_none());
678+
679+
heap.push(1).unwrap();
680+
heap.push(9).unwrap();
681+
heap.push(10).unwrap();
682+
683+
{
684+
let mut val = heap.peek_mut().unwrap();
685+
*val = 7;
686+
}
687+
688+
assert_eq!(heap.pop(), Some(9));
689+
assert_eq!(heap.pop(), Some(7));
690+
assert_eq!(heap.pop(), Some(1));
691+
assert_eq!(heap.pop(), None);
549692
}
550693
}

0 commit comments

Comments
 (0)