@@ -31,7 +31,7 @@ use crate::isize;
31
31
use crate :: iter:: * ;
32
32
use crate :: marker:: { self , Copy , Send , Sized , Sync } ;
33
33
use crate :: mem;
34
- use crate :: ops:: { self , FnMut , Range } ;
34
+ use crate :: ops:: { self , Bound , FnMut , OneSidedRange , Range } ;
35
35
use crate :: option:: Option ;
36
36
use crate :: option:: Option :: { None , Some } ;
37
37
use crate :: ptr:: { self , NonNull } ;
@@ -53,6 +53,24 @@ mod sort;
53
53
// Extension traits
54
54
//
55
55
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
+
56
74
#[ lang = "slice" ]
57
75
#[ cfg( not( test) ) ]
58
76
impl < T > [ T ] {
@@ -2639,6 +2657,227 @@ impl<T> [T] {
2639
2657
{
2640
2658
self . iter ( ) . is_sorted_by_key ( f)
2641
2659
}
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
+ }
2642
2881
}
2643
2882
2644
2883
#[ lang = "slice_u8" ]
0 commit comments