From e694a1938f2ee0e636833fdfe209faf7cf7d6089 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Mon, 26 Oct 2020 04:31:16 +0900 Subject: [PATCH] Add get_pin_ref and get_pin_mut methods to slice --- library/core/src/slice/mod.rs | 60 +++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index b6fd0c4986b64..72325cbd0a1b9 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -15,6 +15,7 @@ use crate::num::NonZeroUsize; use crate::ops::{FnMut, Range, RangeBounds}; use crate::option::Option; use crate::option::Option::{None, Some}; +use crate::pin::Pin; use crate::ptr; use crate::result::Result; use crate::result::Result::{Err, Ok}; @@ -307,6 +308,65 @@ impl [T] { index.get_mut(self) } + /// Returns a pinned reference to an element or subslice depending on the + /// type of index (see [`get`]) or `None` if the index is out of bounds. + /// + /// [`get`]: #method.get + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_get_pin)] + /// use std::pin::Pin; + /// + /// let v = vec![0, 1, 2].into_boxed_slice(); + /// let pinned = Pin::from(v); + /// + /// let x: Option> = pinned.as_ref().get_pin_ref(1); + /// assert_eq!(&1, &*x.unwrap()); + /// ``` + #[unstable(feature = "slice_get_pin", issue = "none")] + #[inline] + pub fn get_pin_ref(self: Pin<&Self>, index: I) -> Option> + where + I: SliceIndex, + { + // SAFETY: `x` is guaranteed to be pinned because it comes from `self` + // which is pinned. + unsafe { self.get_ref().get(index).map(|x| Pin::new_unchecked(x)) } + } + + /// Returns a pinned mutable reference to an element or subslice depending on the + /// type of index (see [`get`]) or `None` if the index is out of bounds. + /// + /// [`get`]: #method.get + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_get_pin)] + /// use std::pin::Pin; + /// + /// let v = vec![0, 1, 2].into_boxed_slice(); + /// let mut pinned = Pin::from(v); + /// + /// if let Some(mut elem) = pinned.as_mut().get_pin_mut(1) { + /// elem.set(10); + /// } + /// assert_eq!(&*pinned, &[0, 10, 2]); + /// ``` + #[unstable(feature = "slice_get_pin", issue = "none")] + #[inline] + pub fn get_pin_mut(self: Pin<&mut Self>, index: I) -> Option> + where + I: SliceIndex, + { + // SAFETY: `get_unchecked_mut` is never used to move the slice inside `self` (`SliceIndex` + // is sealed and all `SliceIndex::get_mut` implementations never move elements). + // `x` is guaranteed to be pinned because it comes from `self` which is pinned. + unsafe { self.get_unchecked_mut().get_mut(index).map(|x| Pin::new_unchecked(x)) } + } + /// Returns a reference to an element or subslice, without doing bounds /// checking. ///