@@ -10,7 +10,7 @@ use crate::cmp::Ordering::{self, Greater, Less};
10
10
use crate :: marker:: Copy ;
11
11
use crate :: mem;
12
12
use crate :: num:: NonZeroUsize ;
13
- use crate :: ops:: { FnMut , Range , RangeBounds } ;
13
+ use crate :: ops:: { Bound , FnMut , OneSidedRange , Range , RangeBounds } ;
14
14
use crate :: option:: Option ;
15
15
use crate :: option:: Option :: { None , Some } ;
16
16
use crate :: ptr;
@@ -82,6 +82,29 @@ pub use index::range;
82
82
#[ unstable( feature = "inherent_ascii_escape" , issue = "77174" ) ]
83
83
pub use ascii:: EscapeAscii ;
84
84
85
+ /// Calculates the direction and split point of a one-sided range.
86
+ ///
87
+ /// This is a helper function for `take` and `take_mut` that returns
88
+ /// the direction of the split (front or back) as well as the index at
89
+ /// which to split. Returns `None` if the split index would overflow.
90
+ #[ inline]
91
+ fn split_point_of ( range : impl OneSidedRange < usize > ) -> Option < ( Direction , usize ) > {
92
+ use Bound :: * ;
93
+
94
+ Some ( match ( range. start_bound ( ) , range. end_bound ( ) ) {
95
+ ( Unbounded , Excluded ( i) ) => ( Direction :: Front , * i) ,
96
+ ( Unbounded , Included ( i) ) => ( Direction :: Front , i. checked_add ( 1 ) ?) ,
97
+ ( Excluded ( i) , Unbounded ) => ( Direction :: Back , i. checked_add ( 1 ) ?) ,
98
+ ( Included ( i) , Unbounded ) => ( Direction :: Back , * i) ,
99
+ _ => unreachable ! ( ) ,
100
+ } )
101
+ }
102
+
103
+ enum Direction {
104
+ Front ,
105
+ Back ,
106
+ }
107
+
85
108
#[ lang = "slice" ]
86
109
#[ cfg( not( test) ) ]
87
110
impl < T > [ T ] {
@@ -3576,6 +3599,245 @@ impl<T> [T] {
3576
3599
{
3577
3600
self . binary_search_by ( |x| if pred ( x) { Less } else { Greater } ) . unwrap_or_else ( |i| i)
3578
3601
}
3602
+
3603
+ /// Removes the subslice corresponding to the given range
3604
+ /// and returns a reference to it.
3605
+ ///
3606
+ /// Returns `None` and does not modify the slice if the given
3607
+ /// range is out of bounds.
3608
+ ///
3609
+ /// Note that this method only accepts one-sided ranges such as
3610
+ /// `2..` or `..6`, but not `2..6`.
3611
+ ///
3612
+ /// # Examples
3613
+ ///
3614
+ /// Taking the first three elements of a slice:
3615
+ ///
3616
+ /// ```
3617
+ /// #![feature(slice_take)]
3618
+ ///
3619
+ /// let mut slice: &[_] = &['a', 'b', 'c', 'd'];
3620
+ /// let mut first_three = slice.take(..3).unwrap();
3621
+ ///
3622
+ /// assert_eq!(slice, &['d']);
3623
+ /// assert_eq!(first_three, &['a', 'b', 'c']);
3624
+ /// ```
3625
+ ///
3626
+ /// Taking the last two elements of a slice:
3627
+ ///
3628
+ /// ```
3629
+ /// #![feature(slice_take)]
3630
+ ///
3631
+ /// let mut slice: &[_] = &['a', 'b', 'c', 'd'];
3632
+ /// let mut tail = slice.take(2..).unwrap();
3633
+ ///
3634
+ /// assert_eq!(slice, &['a', 'b']);
3635
+ /// assert_eq!(tail, &['c', 'd']);
3636
+ /// ```
3637
+ ///
3638
+ /// Getting `None` when `range` is out of bounds:
3639
+ ///
3640
+ /// ```
3641
+ /// #![feature(slice_take)]
3642
+ ///
3643
+ /// let mut slice: &[_] = &['a', 'b', 'c', 'd'];
3644
+ ///
3645
+ /// assert_eq!(None, slice.take(5..));
3646
+ /// assert_eq!(None, slice.take(..5));
3647
+ /// assert_eq!(None, slice.take(..=4));
3648
+ /// let expected: &[char] = &['a', 'b', 'c', 'd'];
3649
+ /// assert_eq!(Some(expected), slice.take(..4));
3650
+ /// ```
3651
+ #[ inline]
3652
+ #[ must_use = "method does not modify the slice if the range is out of bounds" ]
3653
+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
3654
+ pub fn take < ' a , R : OneSidedRange < usize > > ( self : & mut & ' a Self , range : R ) -> Option < & ' a Self > {
3655
+ let ( direction, split_index) = split_point_of ( range) ?;
3656
+ if split_index > self . len ( ) {
3657
+ return None ;
3658
+ }
3659
+ let ( front, back) = self . split_at ( split_index) ;
3660
+ match direction {
3661
+ Direction :: Front => {
3662
+ * self = back;
3663
+ Some ( front)
3664
+ }
3665
+ Direction :: Back => {
3666
+ * self = front;
3667
+ Some ( back)
3668
+ }
3669
+ }
3670
+ }
3671
+
3672
+ /// Removes the subslice corresponding to the given range
3673
+ /// and returns a mutable reference to it.
3674
+ ///
3675
+ /// Returns `None` and does not modify the slice if the given
3676
+ /// range is out of bounds.
3677
+ ///
3678
+ /// Note that this method only accepts one-sided ranges such as
3679
+ /// `2..` or `..6`, but not `2..6`.
3680
+ ///
3681
+ /// # Examples
3682
+ ///
3683
+ /// Taking the first three elements of a slice:
3684
+ ///
3685
+ /// ```
3686
+ /// #![feature(slice_take)]
3687
+ ///
3688
+ /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
3689
+ /// let mut first_three = slice.take_mut(..3).unwrap();
3690
+ ///
3691
+ /// assert_eq!(slice, &mut ['d']);
3692
+ /// assert_eq!(first_three, &mut ['a', 'b', 'c']);
3693
+ /// ```
3694
+ ///
3695
+ /// Taking the last two elements of a slice:
3696
+ ///
3697
+ /// ```
3698
+ /// #![feature(slice_take)]
3699
+ ///
3700
+ /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
3701
+ /// let mut tail = slice.take_mut(2..).unwrap();
3702
+ ///
3703
+ /// assert_eq!(slice, &mut ['a', 'b']);
3704
+ /// assert_eq!(tail, &mut ['c', 'd']);
3705
+ /// ```
3706
+ ///
3707
+ /// Getting `None` when `range` is out of bounds:
3708
+ ///
3709
+ /// ```
3710
+ /// #![feature(slice_take)]
3711
+ ///
3712
+ /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
3713
+ ///
3714
+ /// assert_eq!(None, slice.take_mut(5..));
3715
+ /// assert_eq!(None, slice.take_mut(..5));
3716
+ /// assert_eq!(None, slice.take_mut(..=4));
3717
+ /// let expected: &mut [_] = &mut ['a', 'b', 'c', 'd'];
3718
+ /// assert_eq!(Some(expected), slice.take_mut(..4));
3719
+ /// ```
3720
+ #[ inline]
3721
+ #[ must_use = "method does not modify the slice if the range is out of bounds" ]
3722
+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
3723
+ pub fn take_mut < ' a , R : OneSidedRange < usize > > (
3724
+ self : & mut & ' a mut Self ,
3725
+ range : R ,
3726
+ ) -> Option < & ' a mut Self > {
3727
+ let ( direction, split_index) = split_point_of ( range) ?;
3728
+ if split_index > self . len ( ) {
3729
+ return None ;
3730
+ }
3731
+ let ( front, back) = mem:: take ( self ) . split_at_mut ( split_index) ;
3732
+ match direction {
3733
+ Direction :: Front => {
3734
+ * self = back;
3735
+ Some ( front)
3736
+ }
3737
+ Direction :: Back => {
3738
+ * self = front;
3739
+ Some ( back)
3740
+ }
3741
+ }
3742
+ }
3743
+
3744
+ /// Removes the first element of the slice and returns a reference
3745
+ /// to it.
3746
+ ///
3747
+ /// Returns `None` if the slice is empty.
3748
+ ///
3749
+ /// # Examples
3750
+ ///
3751
+ /// ```
3752
+ /// #![feature(slice_take)]
3753
+ ///
3754
+ /// let mut slice: &[_] = &['a', 'b', 'c'];
3755
+ /// let first = slice.take_first().unwrap();
3756
+ ///
3757
+ /// assert_eq!(slice, &['b', 'c']);
3758
+ /// assert_eq!(first, &'a');
3759
+ /// ```
3760
+ #[ inline]
3761
+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
3762
+ pub fn take_first < ' a > ( self : & mut & ' a Self ) -> Option < & ' a T > {
3763
+ let ( first, rem) = self . split_first ( ) ?;
3764
+ * self = rem;
3765
+ Some ( first)
3766
+ }
3767
+
3768
+ /// Removes the first element of the slice and returns a mutable
3769
+ /// reference to it.
3770
+ ///
3771
+ /// Returns `None` if the slice is empty.
3772
+ ///
3773
+ /// # Examples
3774
+ ///
3775
+ /// ```
3776
+ /// #![feature(slice_take)]
3777
+ ///
3778
+ /// let mut slice: &mut [_] = &mut ['a', 'b', 'c'];
3779
+ /// let first = slice.take_first_mut().unwrap();
3780
+ /// *first = 'd';
3781
+ ///
3782
+ /// assert_eq!(slice, &['b', 'c']);
3783
+ /// assert_eq!(first, &'d');
3784
+ /// ```
3785
+ #[ inline]
3786
+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
3787
+ pub fn take_first_mut < ' a > ( self : & mut & ' a mut Self ) -> Option < & ' a mut T > {
3788
+ let ( first, rem) = mem:: take ( self ) . split_first_mut ( ) ?;
3789
+ * self = rem;
3790
+ Some ( first)
3791
+ }
3792
+
3793
+ /// Removes the last element of the slice and returns a reference
3794
+ /// to it.
3795
+ ///
3796
+ /// Returns `None` if the slice is empty.
3797
+ ///
3798
+ /// # Examples
3799
+ ///
3800
+ /// ```
3801
+ /// #![feature(slice_take)]
3802
+ ///
3803
+ /// let mut slice: &[_] = &['a', 'b', 'c'];
3804
+ /// let last = slice.take_last().unwrap();
3805
+ ///
3806
+ /// assert_eq!(slice, &['a', 'b']);
3807
+ /// assert_eq!(last, &'c');
3808
+ /// ```
3809
+ #[ inline]
3810
+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
3811
+ pub fn take_last < ' a > ( self : & mut & ' a Self ) -> Option < & ' a T > {
3812
+ let ( last, rem) = self . split_last ( ) ?;
3813
+ * self = rem;
3814
+ Some ( last)
3815
+ }
3816
+
3817
+ /// Removes the last element of the slice and returns a mutable
3818
+ /// reference to it.
3819
+ ///
3820
+ /// Returns `None` if the slice is empty.
3821
+ ///
3822
+ /// # Examples
3823
+ ///
3824
+ /// ```
3825
+ /// #![feature(slice_take)]
3826
+ ///
3827
+ /// let mut slice: &mut [_] = &mut ['a', 'b', 'c'];
3828
+ /// let last = slice.take_last_mut().unwrap();
3829
+ /// *last = 'd';
3830
+ ///
3831
+ /// assert_eq!(slice, &['a', 'b']);
3832
+ /// assert_eq!(last, &'d');
3833
+ /// ```
3834
+ #[ inline]
3835
+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
3836
+ pub fn take_last_mut < ' a > ( self : & mut & ' a mut Self ) -> Option < & ' a mut T > {
3837
+ let ( last, rem) = mem:: take ( self ) . split_last_mut ( ) ?;
3838
+ * self = rem;
3839
+ Some ( last)
3840
+ }
3579
3841
}
3580
3842
3581
3843
trait CloneFromSpec < T > {
0 commit comments