@@ -12,6 +12,7 @@ use core::{
12
12
fmt,
13
13
marker:: PhantomData ,
14
14
mem:: { self , ManuallyDrop } ,
15
+ ops:: { Deref , DerefMut } ,
15
16
ptr, slice,
16
17
} ;
17
18
@@ -226,6 +227,44 @@ where
226
227
self . 0 . data . as_slice ( ) . get ( 0 )
227
228
}
228
229
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
+
229
268
/// Removes the *top* (greatest if max-heap, smallest if min-heap) item from the binary heap and
230
269
/// returns it, or None if it is empty.
231
270
///
@@ -390,6 +429,78 @@ impl<'a, T> Hole<'a, T> {
390
429
}
391
430
}
392
431
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
+
393
504
impl < ' a , T > Drop for Hole < ' a , T > {
394
505
#[ inline]
395
506
fn drop ( & mut self ) {
@@ -510,6 +621,22 @@ mod tests {
510
621
assert_eq ! ( heap. pop( ) , Some ( 36 ) ) ;
511
622
assert_eq ! ( heap. pop( ) , Some ( 100 ) ) ;
512
623
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 ) ;
513
640
}
514
641
515
642
#[ test]
@@ -546,5 +673,21 @@ mod tests {
546
673
assert_eq ! ( heap. pop( ) , Some ( 2 ) ) ;
547
674
assert_eq ! ( heap. pop( ) , Some ( 1 ) ) ;
548
675
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 ) ;
549
692
}
550
693
}
0 commit comments