add Vec::peek_mut
This commit is contained in:
parent
59aa1e8730
commit
188c40126d
4 changed files with 102 additions and 0 deletions
|
|
@ -109,6 +109,11 @@ mod in_place_collect;
|
|||
|
||||
mod partial_eq;
|
||||
|
||||
#[unstable(feature = "vec_peek_mut", issue = "122742")]
|
||||
pub use self::peek_mut::PeekMut;
|
||||
|
||||
mod peek_mut;
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use self::spec_from_elem::SpecFromElem;
|
||||
|
||||
|
|
@ -729,6 +734,36 @@ impl<T> Vec<T> {
|
|||
pub unsafe fn from_parts(ptr: NonNull<T>, length: usize, capacity: usize) -> Self {
|
||||
unsafe { Self::from_parts_in(ptr, length, capacity, Global) }
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the greatest item in the binary heap, or
|
||||
/// `None` if it is empty.
|
||||
///
|
||||
/// Note: If the `PeekMut` value is leaked, some heap elements might get
|
||||
/// leaked along with it, but the remaining elements will remain a valid
|
||||
/// heap.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let mut vec = Vec::new();
|
||||
/// assert!(vec.peek_mut().is_none());
|
||||
///
|
||||
/// vec.push(1);
|
||||
/// vec.push(5);
|
||||
/// vec.push(2);
|
||||
/// assert_eq!(vec.last(), Some(&2));
|
||||
/// if let Some(mut val) = vec.peek_mut() {
|
||||
/// *val = 0;
|
||||
/// }
|
||||
/// assert_eq!(vec.last(), Some(&0));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "vec_peek_mut", issue = "122742")]
|
||||
pub fn peek_mut(&mut self) -> Option<PeekMut<'_, T>> {
|
||||
PeekMut::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, A: Allocator> Vec<T, A> {
|
||||
|
|
|
|||
55
library/alloc/src/vec/peek_mut.rs
Normal file
55
library/alloc/src/vec/peek_mut.rs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
use core::ops::{Deref, DerefMut};
|
||||
|
||||
use super::Vec;
|
||||
use crate::fmt;
|
||||
|
||||
/// Structure wrapping a mutable reference to the last item in a
|
||||
/// `Vec`.
|
||||
///
|
||||
/// This `struct` is created by the [`peek_mut`] method on [`Vec`]. See
|
||||
/// its documentation for more.
|
||||
///
|
||||
/// [`peek_mut`]: Vec::peek_mut
|
||||
#[unstable(feature = "vec_peek_mut", issue = "122742")]
|
||||
pub struct PeekMut<'a, T> {
|
||||
vec: &'a mut Vec<T>,
|
||||
}
|
||||
|
||||
#[unstable(feature = "vec_peek_mut", issue = "122742")]
|
||||
impl<T: fmt::Debug> fmt::Debug for PeekMut<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("PeekMut").field(self.deref()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> PeekMut<'a, T> {
|
||||
pub(crate) fn new(vec: &'a mut Vec<T>) -> Option<Self> {
|
||||
if vec.is_empty() { None } else { Some(Self { vec }) }
|
||||
}
|
||||
|
||||
/// Removes the peeked value from the vector and returns it.
|
||||
#[unstable(feature = "vec_peek_mut", issue = "122742")]
|
||||
pub fn pop(self) -> T {
|
||||
// SAFETY: PeekMut is only constructed if the vec is non-empty
|
||||
unsafe { self.vec.pop().unwrap_unchecked() }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "vec_peek_mut", issue = "122742")]
|
||||
impl<'a, T> Deref for PeekMut<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
// SAFETY: PeekMut is only constructed if the vec is non-empty
|
||||
unsafe { self.vec.get_unchecked(self.vec.len() - 1) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "vec_peek_mut", issue = "122742")]
|
||||
impl<'a, T> DerefMut for PeekMut<'a, T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
let idx = self.vec.len() - 1;
|
||||
// SAFETY: PeekMut is only constructed if the vec is non-empty
|
||||
unsafe { self.vec.get_unchecked_mut(idx) }
|
||||
}
|
||||
}
|
||||
|
|
@ -42,6 +42,7 @@
|
|||
#![feature(trusted_random_access)]
|
||||
#![feature(try_reserve_kind)]
|
||||
#![feature(try_trait_v2)]
|
||||
#![feature(vec_peek_mut)]
|
||||
// tidy-alphabetical-end
|
||||
//
|
||||
// Language features:
|
||||
|
|
|
|||
|
|
@ -2698,6 +2698,17 @@ fn test_pop_if_mutates() {
|
|||
assert_eq!(v, [2]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_peek_mut() {
|
||||
let mut vec = Vec::new();
|
||||
assert!(vec.peek_mut().is_none());
|
||||
vec.push(1);
|
||||
vec.push(2);
|
||||
assert_eq!(vec.peek_mut(), Some(2));
|
||||
*vec.peek_mut() = 0;
|
||||
assert_eq!(vec.peek_mut(), Some(0));
|
||||
}
|
||||
|
||||
/// This assortment of tests, in combination with miri, verifies we handle UB on fishy arguments
|
||||
/// in the stdlib. Draining and extending the allocation are fairly well-tested earlier, but
|
||||
/// `vec.insert(usize::MAX, val)` once slipped by!
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue