@@ -12,7 +12,7 @@ use crate::cmp::Ordering::{self, Equal, Greater, Less};
1212use crate :: marker:: Copy ;
1313use crate :: mem;
1414use crate :: num:: NonZeroUsize ;
15- use crate :: ops:: { FnMut , Range , RangeBounds } ;
15+ use crate :: ops:: { Bound , FnMut , OneSidedRange , Range , RangeBounds } ;
1616use crate :: option:: Option ;
1717use crate :: option:: Option :: { None , Some } ;
1818use crate :: ptr;
@@ -73,6 +73,24 @@ pub use sort::heapsort;
7373#[ stable( feature = "slice_get_slice" , since = "1.28.0" ) ]
7474pub use index:: SliceIndex ;
7575
76+ /// Calculates the direction and split point of a one-sided range.
77+ ///
78+ /// Helper for `take` and `take_mut` which returns a boolean
79+ /// indicating whether the front of the split is being taken
80+ /// (as opposed to the back), as well as a number indicating the
81+ /// index at which to split. Returns `None` if the split index would
82+ /// overflow `usize`.
83+ #[ inline]
84+ fn take_split_point ( range : impl OneSidedRange < usize > ) -> Option < ( bool , usize ) > {
85+ Some ( match ( range. start_bound ( ) , range. end_bound ( ) ) {
86+ ( Bound :: Unbounded , Bound :: Excluded ( i) ) => ( true , * i) ,
87+ ( Bound :: Unbounded , Bound :: Included ( i) ) => ( true , i. checked_add ( 1 ) ?) ,
88+ ( Bound :: Excluded ( i) , Bound :: Unbounded ) => ( false , i. checked_add ( 1 ) ?) ,
89+ ( Bound :: Included ( i) , Bound :: Unbounded ) => ( false , * i) ,
90+ _ => unreachable ! ( ) ,
91+ } )
92+ }
93+
7694#[ lang = "slice" ]
7795#[ cfg( not( test) ) ]
7896impl < T > [ T ] {
@@ -3169,6 +3187,227 @@ impl<T> [T] {
31693187
31703188 left
31713189 }
3190+
3191+ /// Removes and returns the portion of the slice specified by `range`.
3192+ ///
3193+ /// If the provided `range` starts or ends outside of the slice,
3194+ /// `None` is returned and the slice is not modified.
3195+ ///
3196+ /// # Examples
3197+ ///
3198+ /// Taking the first three items from a slice (via `..3`):
3199+ ///
3200+ /// ```
3201+ /// #![feature(slice_take)]
3202+ ///
3203+ /// let mut slice: &[_] = &['a', 'b', 'c', 'd'];
3204+ /// let mut first_three = slice.take(..3).unwrap();
3205+ ///
3206+ /// assert_eq!(slice, &['d']);
3207+ /// assert_eq!(first_three, &['a', 'b', 'c']);
3208+ /// ```
3209+ ///
3210+ /// Taking the tail of a slice starting at index two (via `2..`):
3211+ ///
3212+ /// ```
3213+ /// #![feature(slice_take)]
3214+ ///
3215+ /// let mut slice: &[_] = &['a', 'b', 'c', 'd'];
3216+ /// let mut tail = slice.take(2..).unwrap();
3217+ ///
3218+ /// assert_eq!(slice, &['a', 'b']);
3219+ /// assert_eq!(tail, &['c', 'd']);
3220+ /// ```
3221+ ///
3222+ /// Getting `None` when `range` starts or ends outside of the slice:
3223+ ///
3224+ /// ```
3225+ /// #![feature(slice_take)]
3226+ ///
3227+ /// let mut slice: &[_] = &['a', 'b', 'c', 'd'];
3228+ ///
3229+ /// assert_eq!(None, slice.take(5..));
3230+ /// assert_eq!(None, slice.take(..5));
3231+ /// assert_eq!(None, slice.take(..=4));
3232+ /// let expected: &[char] = &['a', 'b', 'c', 'd'];
3233+ /// assert_eq!(Some(expected), slice.take(..4));
3234+ /// ```
3235+ #[ inline]
3236+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
3237+ pub fn take < ' a , R : OneSidedRange < usize > > ( self : & mut & ' a Self , range : R ) -> Option < & ' a Self > {
3238+ let ( taking_front, split_index) = take_split_point ( range) ?;
3239+ if split_index > self . len ( ) {
3240+ return None ;
3241+ }
3242+ let original = crate :: mem:: take ( self ) ;
3243+ let ( front, back) = original. split_at ( split_index) ;
3244+ if taking_front {
3245+ * self = back;
3246+ Some ( front)
3247+ } else {
3248+ * self = front;
3249+ Some ( back)
3250+ }
3251+ }
3252+
3253+ /// Removes and returns the portion of the mutable slice specified by `range`.
3254+ ///
3255+ /// If the provided `range` starts or ends outside of the slice,
3256+ /// `None` is returned and the slice is not modified.
3257+ ///
3258+ /// # Examples
3259+ ///
3260+ /// Taking the first three items from a slice (via `..3`):
3261+ ///
3262+ /// ```
3263+ /// #![feature(slice_take)]
3264+ ///
3265+ /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
3266+ /// let mut first_three = slice.take_mut(..3).unwrap();
3267+ ///
3268+ /// assert_eq!(slice, &mut ['d']);
3269+ /// assert_eq!(first_three, &mut ['a', 'b', 'c']);
3270+ /// ```
3271+ ///
3272+ /// Taking the tail of a slice starting at index two (via `2..`):
3273+ ///
3274+ /// ```
3275+ /// #![feature(slice_take)]
3276+ ///
3277+ /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
3278+ /// let mut tail = slice.take_mut(2..).unwrap();
3279+ ///
3280+ /// assert_eq!(slice, &mut ['a', 'b']);
3281+ /// assert_eq!(tail, &mut ['c', 'd']);
3282+ /// ```
3283+ ///
3284+ /// Getting `None` when `range` starts or ends outside of the slice:
3285+ ///
3286+ /// ```
3287+ /// #![feature(slice_take)]
3288+ ///
3289+ /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
3290+ ///
3291+ /// assert_eq!(None, slice.take_mut(5..));
3292+ /// assert_eq!(None, slice.take_mut(..5));
3293+ /// assert_eq!(None, slice.take_mut(..=4));
3294+ /// let expected: &mut [_] = &mut ['a', 'b', 'c', 'd'];
3295+ /// assert_eq!(Some(expected), slice.take_mut(..4));
3296+ /// ```
3297+ #[ inline]
3298+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
3299+ pub fn take_mut < ' a , R : OneSidedRange < usize > > (
3300+ self : & mut & ' a mut Self ,
3301+ range : R ,
3302+ ) -> Option < & ' a mut Self > {
3303+ let ( taking_front, split_index) = take_split_point ( range) ?;
3304+ if split_index > self . len ( ) {
3305+ return None ;
3306+ }
3307+ let original = crate :: mem:: take ( self ) ;
3308+ let ( front, back) = original. split_at_mut ( split_index) ;
3309+ if taking_front {
3310+ * self = back;
3311+ Some ( front)
3312+ } else {
3313+ * self = front;
3314+ Some ( back)
3315+ }
3316+ }
3317+
3318+ /// Takes the first element out of the slice.
3319+ ///
3320+ /// Returns a reference pointing to the first element of the old slice.
3321+ ///
3322+ /// Returns `None` if the slice is empty.
3323+ ///
3324+ /// # Examples
3325+ ///
3326+ /// ```
3327+ /// #![feature(slice_take)]
3328+ ///
3329+ /// let mut slice: &[_] = &['a', 'b', 'c'];
3330+ /// let first = slice.take_first().unwrap();
3331+ ///
3332+ /// assert_eq!(slice, &['b', 'c']);
3333+ /// assert_eq!(first, &'a');
3334+ /// ```
3335+ #[ inline]
3336+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
3337+ pub fn take_first < ' a > ( self : & mut & ' a Self ) -> Option < & ' a T > {
3338+ self . take ( ..=0 ) . map ( |res| & res[ 0 ] )
3339+ }
3340+
3341+ /// Takes the first element out of the mutable slice.
3342+ ///
3343+ /// Returns a mutable reference pointing to the first element of the old slice.
3344+ ///
3345+ /// Returns `None` if the slice is empty.
3346+ ///
3347+ /// # Examples
3348+ ///
3349+ /// ```
3350+ /// #![feature(slice_take)]
3351+ ///
3352+ /// let mut slice: &mut [_] = &mut ['a', 'b', 'c'];
3353+ /// let first = slice.take_first_mut().unwrap();
3354+ /// *first = 'd';
3355+ ///
3356+ /// assert_eq!(slice, &['b', 'c']);
3357+ /// assert_eq!(first, &'d');
3358+ /// ```
3359+ #[ inline]
3360+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
3361+ pub fn take_first_mut < ' a > ( self : & mut & ' a mut Self ) -> Option < & ' a mut T > {
3362+ self . take_mut ( ..=0 ) . map ( |res| & mut res[ 0 ] )
3363+ }
3364+
3365+ /// Takes the last element out of the slice.
3366+ ///
3367+ /// Returns a reference pointing to the last element of the old slice.
3368+ ///
3369+ /// Returns `None` if the slice is empty.
3370+ ///
3371+ /// # Examples
3372+ ///
3373+ /// ```
3374+ /// #![feature(slice_take)]
3375+ ///
3376+ /// let mut slice: &[_] = &['a', 'b', 'c'];
3377+ /// let last = slice.take_last().unwrap();
3378+ ///
3379+ /// assert_eq!(slice, &['a', 'b']);
3380+ /// assert_eq!(last, &'c');
3381+ /// ```
3382+ #[ inline]
3383+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
3384+ pub fn take_last < ' a > ( self : & mut & ' a Self ) -> Option < & ' a T > {
3385+ self . take ( ( self . len ( ) - 1 ) ..) . map ( |res| & res[ 0 ] )
3386+ }
3387+
3388+ /// Takes the last element out of the mutable slice.
3389+ ///
3390+ /// Returns a mutable reference pointing to the last element of the old slice.
3391+ ///
3392+ /// Returns `None` if the slice is empty.
3393+ ///
3394+ /// # Examples
3395+ ///
3396+ /// ```
3397+ /// #![feature(slice_take)]
3398+ ///
3399+ /// let mut slice: &mut [_] = &mut ['a', 'b', 'c'];
3400+ /// let last = slice.take_last_mut().unwrap();
3401+ /// *last = 'd';
3402+ ///
3403+ /// assert_eq!(slice, &['a', 'b']);
3404+ /// assert_eq!(last, &'d');
3405+ /// ```
3406+ #[ inline]
3407+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
3408+ pub fn take_last_mut < ' a > ( self : & mut & ' a mut Self ) -> Option < & ' a mut T > {
3409+ self . take_mut ( ( self . len ( ) - 1 ) ..) . map ( |res| & mut res[ 0 ] )
3410+ }
31723411}
31733412
31743413#[ stable( feature = "rust1" , since = "1.0.0" ) ]
0 commit comments