@@ -31,7 +31,7 @@ use crate::isize;
3131use crate :: iter:: * ;
3232use crate :: marker:: { self , Copy , Send , Sized , Sync } ;
3333use crate :: mem;
34- use crate :: ops:: { self , FnMut , Range } ;
34+ use crate :: ops:: { self , Bound , FnMut , OneSidedRange , Range } ;
3535use crate :: option:: Option ;
3636use crate :: option:: Option :: { None , Some } ;
3737use crate :: ptr:: { self , NonNull } ;
@@ -53,6 +53,24 @@ mod sort;
5353// Extension traits
5454//
5555
56+ /// Calculates the direction and split point of a one-sided range.
57+ ///
58+ /// Helper for `take` and `take_mut` which returns a boolean
59+ /// indicating whether the front of the split is being taken
60+ /// (as opposed to the back), as well as a number indicating the
61+ /// index at which to split. Returns `None` if the split index would
62+ /// overflow `usize`.
63+ #[ inline]
64+ fn take_split_point ( range : impl OneSidedRange < usize > ) -> Option < ( bool , usize ) > {
65+ Some ( match ( range. start_bound ( ) , range. end_bound ( ) ) {
66+ ( Bound :: Unbounded , Bound :: Excluded ( i) ) => ( true , * i) ,
67+ ( Bound :: Unbounded , Bound :: Included ( i) ) => ( true , i. checked_add ( 1 ) ?) ,
68+ ( Bound :: Excluded ( i) , Bound :: Unbounded ) => ( false , i. checked_add ( 1 ) ?) ,
69+ ( Bound :: Included ( i) , Bound :: Unbounded ) => ( false , * i) ,
70+ _ => unreachable ! ( ) ,
71+ } )
72+ }
73+
5674#[ lang = "slice" ]
5775#[ cfg( not( test) ) ]
5876impl < T > [ T ] {
@@ -2639,6 +2657,227 @@ impl<T> [T] {
26392657 {
26402658 self . iter ( ) . is_sorted_by_key ( f)
26412659 }
2660+
2661+ /// Removes and returns the portion of the slice specified by `range`.
2662+ ///
2663+ /// If the provided `range` starts or ends outside of the slice,
2664+ /// `None` is returned and the slice is not modified.
2665+ ///
2666+ /// # Examples
2667+ ///
2668+ /// Taking the first three items from a slice (via `..3`):
2669+ ///
2670+ /// ```
2671+ /// #![feature(slice_take)]
2672+ ///
2673+ /// let mut slice: &[_] = &['a', 'b', 'c', 'd'];
2674+ /// let mut first_three = slice.take(..3).unwrap();
2675+ ///
2676+ /// assert_eq!(slice, &['d']);
2677+ /// assert_eq!(first_three, &['a', 'b', 'c']);
2678+ /// ```
2679+ ///
2680+ /// Taking the tail of a slice starting at index two (via `2..`):
2681+ ///
2682+ /// ```
2683+ /// #![feature(slice_take)]
2684+ ///
2685+ /// let mut slice: &[_] = &['a', 'b', 'c', 'd'];
2686+ /// let mut tail = slice.take(2..).unwrap();
2687+ ///
2688+ /// assert_eq!(slice, &['a', 'b']);
2689+ /// assert_eq!(tail, &['c', 'd']);
2690+ /// ```
2691+ ///
2692+ /// Getting `None` when `range` starts or ends outside of the slice:
2693+ ///
2694+ /// ```
2695+ /// #![feature(slice_take)]
2696+ ///
2697+ /// let mut slice: &[_] = &['a', 'b', 'c', 'd'];
2698+ ///
2699+ /// assert_eq!(None, slice.take(5..));
2700+ /// assert_eq!(None, slice.take(..5));
2701+ /// assert_eq!(None, slice.take(..=4));
2702+ /// let expected: &[char] = &['a', 'b', 'c', 'd'];
2703+ /// assert_eq!(Some(expected), slice.take(..4));
2704+ /// ```
2705+ #[ inline]
2706+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
2707+ pub fn take < ' a , R : OneSidedRange < usize > > ( self : & mut & ' a Self , range : R ) -> Option < & ' a Self > {
2708+ let ( taking_front, split_index) = take_split_point ( range) ?;
2709+ if split_index > self . len ( ) {
2710+ return None ;
2711+ }
2712+ let original = crate :: mem:: take ( self ) ;
2713+ let ( front, back) = original. split_at ( split_index) ;
2714+ if taking_front {
2715+ * self = back;
2716+ Some ( front)
2717+ } else {
2718+ * self = front;
2719+ Some ( back)
2720+ }
2721+ }
2722+
2723+ /// Removes and returns the portion of the mutable slice specified by `range`.
2724+ ///
2725+ /// If the provided `range` starts or ends outside of the slice,
2726+ /// `None` is returned and the slice is not modified.
2727+ ///
2728+ /// # Examples
2729+ ///
2730+ /// Taking the first three items from a slice (via `..3`):
2731+ ///
2732+ /// ```
2733+ /// #![feature(slice_take)]
2734+ ///
2735+ /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
2736+ /// let mut first_three = slice.take_mut(..3).unwrap();
2737+ ///
2738+ /// assert_eq!(slice, &mut ['d']);
2739+ /// assert_eq!(first_three, &mut ['a', 'b', 'c']);
2740+ /// ```
2741+ ///
2742+ /// Taking the tail of a slice starting at index two (via `2..`):
2743+ ///
2744+ /// ```
2745+ /// #![feature(slice_take)]
2746+ ///
2747+ /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
2748+ /// let mut tail = slice.take_mut(2..).unwrap();
2749+ ///
2750+ /// assert_eq!(slice, &mut ['a', 'b']);
2751+ /// assert_eq!(tail, &mut ['c', 'd']);
2752+ /// ```
2753+ ///
2754+ /// Getting `None` when `range` starts or ends outside of the slice:
2755+ ///
2756+ /// ```
2757+ /// #![feature(slice_take)]
2758+ ///
2759+ /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
2760+ ///
2761+ /// assert_eq!(None, slice.take_mut(5..));
2762+ /// assert_eq!(None, slice.take_mut(..5));
2763+ /// assert_eq!(None, slice.take_mut(..=4));
2764+ /// let expected: &mut [_] = &mut ['a', 'b', 'c', 'd'];
2765+ /// assert_eq!(Some(expected), slice.take_mut(..4));
2766+ /// ```
2767+ #[ inline]
2768+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
2769+ pub fn take_mut < ' a , R : OneSidedRange < usize > > (
2770+ self : & mut & ' a mut Self ,
2771+ range : R ,
2772+ ) -> Option < & ' a mut Self > {
2773+ let ( taking_front, split_index) = take_split_point ( range) ?;
2774+ if split_index > self . len ( ) {
2775+ return None ;
2776+ }
2777+ let original = crate :: mem:: take ( self ) ;
2778+ let ( front, back) = original. split_at_mut ( split_index) ;
2779+ if taking_front {
2780+ * self = back;
2781+ Some ( front)
2782+ } else {
2783+ * self = front;
2784+ Some ( back)
2785+ }
2786+ }
2787+
2788+ /// Takes the first element out of the slice.
2789+ ///
2790+ /// Returns a reference pointing to the first element of the old slice.
2791+ ///
2792+ /// Returns `None` if the slice is empty.
2793+ ///
2794+ /// # Examples
2795+ ///
2796+ /// ```
2797+ /// #![feature(slice_take)]
2798+ ///
2799+ /// let mut slice: &[_] = &['a', 'b', 'c'];
2800+ /// let first = slice.take_first().unwrap();
2801+ ///
2802+ /// assert_eq!(slice, &['b', 'c']);
2803+ /// assert_eq!(first, &'a');
2804+ /// ```
2805+ #[ inline]
2806+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
2807+ pub fn take_first < ' a > ( self : & mut & ' a Self ) -> Option < & ' a T > {
2808+ self . take ( ..=0 ) . map ( |res| & res[ 0 ] )
2809+ }
2810+
2811+ /// Takes the first element out of the mutable slice.
2812+ ///
2813+ /// Returns a mutable reference pointing to the first element of the old slice.
2814+ ///
2815+ /// Returns `None` if the slice is empty.
2816+ ///
2817+ /// # Examples
2818+ ///
2819+ /// ```
2820+ /// #![feature(slice_take)]
2821+ ///
2822+ /// let mut slice: &mut [_] = &mut ['a', 'b', 'c'];
2823+ /// let first = slice.take_first_mut().unwrap();
2824+ /// *first = 'd';
2825+ ///
2826+ /// assert_eq!(slice, &['b', 'c']);
2827+ /// assert_eq!(first, &'d');
2828+ /// ```
2829+ #[ inline]
2830+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
2831+ pub fn take_first_mut < ' a > ( self : & mut & ' a mut Self ) -> Option < & ' a mut T > {
2832+ self . take_mut ( ..=0 ) . map ( |res| & mut res[ 0 ] )
2833+ }
2834+
2835+ /// Takes the last element out of the slice.
2836+ ///
2837+ /// Returns a reference pointing to the last element of the old slice.
2838+ ///
2839+ /// Returns `None` if the slice is empty.
2840+ ///
2841+ /// # Examples
2842+ ///
2843+ /// ```
2844+ /// #![feature(slice_take)]
2845+ ///
2846+ /// let mut slice: &[_] = &['a', 'b', 'c'];
2847+ /// let last = slice.take_last().unwrap();
2848+ ///
2849+ /// assert_eq!(slice, &['a', 'b']);
2850+ /// assert_eq!(last, &'c');
2851+ /// ```
2852+ #[ inline]
2853+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
2854+ pub fn take_last < ' a > ( self : & mut & ' a Self ) -> Option < & ' a T > {
2855+ self . take ( ( self . len ( ) - 1 ) ..) . map ( |res| & res[ 0 ] )
2856+ }
2857+
2858+ /// Takes the last element out of the mutable slice.
2859+ ///
2860+ /// Returns a mutable reference pointing to the last element of the old slice.
2861+ ///
2862+ /// Returns `None` if the slice is empty.
2863+ ///
2864+ /// # Examples
2865+ ///
2866+ /// ```
2867+ /// #![feature(slice_take)]
2868+ ///
2869+ /// let mut slice: &mut [_] = &mut ['a', 'b', 'c'];
2870+ /// let last = slice.take_last_mut().unwrap();
2871+ /// *last = 'd';
2872+ ///
2873+ /// assert_eq!(slice, &['a', 'b']);
2874+ /// assert_eq!(last, &'d');
2875+ /// ```
2876+ #[ inline]
2877+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
2878+ pub fn take_last_mut < ' a > ( self : & mut & ' a mut Self ) -> Option < & ' a mut T > {
2879+ self . take_mut ( ( self . len ( ) - 1 ) ..) . map ( |res| & mut res[ 0 ] )
2880+ }
26422881}
26432882
26442883#[ lang = "slice_u8" ]
0 commit comments