@@ -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 ] {
@@ -3517,6 +3540,245 @@ impl<T> [T] {
3517
3540
{
3518
3541
self . binary_search_by ( |x| if pred ( x) { Less } else { Greater } ) . unwrap_or_else ( |i| i)
3519
3542
}
3543
+
3544
+ /// Removes the subslice corresponding to the given range
3545
+ /// and returns a reference to it.
3546
+ ///
3547
+ /// Returns `None` and does not modify the slice if the given
3548
+ /// range is out of bounds.
3549
+ ///
3550
+ /// Note that this method only accepts one-sided ranges such as
3551
+ /// `2..` or `..6`, but not `2..6`.
3552
+ ///
3553
+ /// # Examples
3554
+ ///
3555
+ /// Taking the first three elements of a slice:
3556
+ ///
3557
+ /// ```
3558
+ /// #![feature(slice_take)]
3559
+ ///
3560
+ /// let mut slice: &[_] = &['a', 'b', 'c', 'd'];
3561
+ /// let mut first_three = slice.take(..3).unwrap();
3562
+ ///
3563
+ /// assert_eq!(slice, &['d']);
3564
+ /// assert_eq!(first_three, &['a', 'b', 'c']);
3565
+ /// ```
3566
+ ///
3567
+ /// Taking the last two elements of a slice:
3568
+ ///
3569
+ /// ```
3570
+ /// #![feature(slice_take)]
3571
+ ///
3572
+ /// let mut slice: &[_] = &['a', 'b', 'c', 'd'];
3573
+ /// let mut tail = slice.take(2..).unwrap();
3574
+ ///
3575
+ /// assert_eq!(slice, &['a', 'b']);
3576
+ /// assert_eq!(tail, &['c', 'd']);
3577
+ /// ```
3578
+ ///
3579
+ /// Getting `None` when `range` is out of bounds:
3580
+ ///
3581
+ /// ```
3582
+ /// #![feature(slice_take)]
3583
+ ///
3584
+ /// let mut slice: &[_] = &['a', 'b', 'c', 'd'];
3585
+ ///
3586
+ /// assert_eq!(None, slice.take(5..));
3587
+ /// assert_eq!(None, slice.take(..5));
3588
+ /// assert_eq!(None, slice.take(..=4));
3589
+ /// let expected: &[char] = &['a', 'b', 'c', 'd'];
3590
+ /// assert_eq!(Some(expected), slice.take(..4));
3591
+ /// ```
3592
+ #[ inline]
3593
+ #[ must_use = "method does not modify the slice if the range is out of bounds" ]
3594
+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
3595
+ pub fn take < ' a , R : OneSidedRange < usize > > ( self : & mut & ' a Self , range : R ) -> Option < & ' a Self > {
3596
+ let ( direction, split_index) = split_point_of ( range) ?;
3597
+ if split_index > self . len ( ) {
3598
+ return None ;
3599
+ }
3600
+ let ( front, back) = self . split_at ( split_index) ;
3601
+ match direction {
3602
+ Direction :: Front => {
3603
+ * self = back;
3604
+ Some ( front)
3605
+ }
3606
+ Direction :: Back => {
3607
+ * self = front;
3608
+ Some ( back)
3609
+ }
3610
+ }
3611
+ }
3612
+
3613
+ /// Removes the subslice corresponding to the given range
3614
+ /// and returns a mutable reference to it.
3615
+ ///
3616
+ /// Returns `None` and does not modify the slice if the given
3617
+ /// range is out of bounds.
3618
+ ///
3619
+ /// Note that this method only accepts one-sided ranges such as
3620
+ /// `2..` or `..6`, but not `2..6`.
3621
+ ///
3622
+ /// # Examples
3623
+ ///
3624
+ /// Taking the first three elements of a slice:
3625
+ ///
3626
+ /// ```
3627
+ /// #![feature(slice_take)]
3628
+ ///
3629
+ /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
3630
+ /// let mut first_three = slice.take_mut(..3).unwrap();
3631
+ ///
3632
+ /// assert_eq!(slice, &mut ['d']);
3633
+ /// assert_eq!(first_three, &mut ['a', 'b', 'c']);
3634
+ /// ```
3635
+ ///
3636
+ /// Taking the last two elements of a slice:
3637
+ ///
3638
+ /// ```
3639
+ /// #![feature(slice_take)]
3640
+ ///
3641
+ /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
3642
+ /// let mut tail = slice.take_mut(2..).unwrap();
3643
+ ///
3644
+ /// assert_eq!(slice, &mut ['a', 'b']);
3645
+ /// assert_eq!(tail, &mut ['c', 'd']);
3646
+ /// ```
3647
+ ///
3648
+ /// Getting `None` when `range` is out of bounds:
3649
+ ///
3650
+ /// ```
3651
+ /// #![feature(slice_take)]
3652
+ ///
3653
+ /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
3654
+ ///
3655
+ /// assert_eq!(None, slice.take_mut(5..));
3656
+ /// assert_eq!(None, slice.take_mut(..5));
3657
+ /// assert_eq!(None, slice.take_mut(..=4));
3658
+ /// let expected: &mut [_] = &mut ['a', 'b', 'c', 'd'];
3659
+ /// assert_eq!(Some(expected), slice.take_mut(..4));
3660
+ /// ```
3661
+ #[ inline]
3662
+ #[ must_use = "method does not modify the slice if the range is out of bounds" ]
3663
+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
3664
+ pub fn take_mut < ' a , R : OneSidedRange < usize > > (
3665
+ self : & mut & ' a mut Self ,
3666
+ range : R ,
3667
+ ) -> Option < & ' a mut Self > {
3668
+ let ( direction, split_index) = split_point_of ( range) ?;
3669
+ if split_index > self . len ( ) {
3670
+ return None ;
3671
+ }
3672
+ let ( front, back) = mem:: take ( self ) . split_at_mut ( split_index) ;
3673
+ match direction {
3674
+ Direction :: Front => {
3675
+ * self = back;
3676
+ Some ( front)
3677
+ }
3678
+ Direction :: Back => {
3679
+ * self = front;
3680
+ Some ( back)
3681
+ }
3682
+ }
3683
+ }
3684
+
3685
+ /// Removes the first element of the slice and returns a reference
3686
+ /// to it.
3687
+ ///
3688
+ /// Returns `None` if the slice is empty.
3689
+ ///
3690
+ /// # Examples
3691
+ ///
3692
+ /// ```
3693
+ /// #![feature(slice_take)]
3694
+ ///
3695
+ /// let mut slice: &[_] = &['a', 'b', 'c'];
3696
+ /// let first = slice.take_first().unwrap();
3697
+ ///
3698
+ /// assert_eq!(slice, &['b', 'c']);
3699
+ /// assert_eq!(first, &'a');
3700
+ /// ```
3701
+ #[ inline]
3702
+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
3703
+ pub fn take_first < ' a > ( self : & mut & ' a Self ) -> Option < & ' a T > {
3704
+ let ( first, rem) = self . split_first ( ) ?;
3705
+ * self = rem;
3706
+ Some ( first)
3707
+ }
3708
+
3709
+ /// Removes the first element of the slice and returns a mutable
3710
+ /// reference to it.
3711
+ ///
3712
+ /// Returns `None` if the slice is empty.
3713
+ ///
3714
+ /// # Examples
3715
+ ///
3716
+ /// ```
3717
+ /// #![feature(slice_take)]
3718
+ ///
3719
+ /// let mut slice: &mut [_] = &mut ['a', 'b', 'c'];
3720
+ /// let first = slice.take_first_mut().unwrap();
3721
+ /// *first = 'd';
3722
+ ///
3723
+ /// assert_eq!(slice, &['b', 'c']);
3724
+ /// assert_eq!(first, &'d');
3725
+ /// ```
3726
+ #[ inline]
3727
+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
3728
+ pub fn take_first_mut < ' a > ( self : & mut & ' a mut Self ) -> Option < & ' a mut T > {
3729
+ let ( first, rem) = mem:: take ( self ) . split_first_mut ( ) ?;
3730
+ * self = rem;
3731
+ Some ( first)
3732
+ }
3733
+
3734
+ /// Removes the last element of the slice and returns a reference
3735
+ /// to it.
3736
+ ///
3737
+ /// Returns `None` if the slice is empty.
3738
+ ///
3739
+ /// # Examples
3740
+ ///
3741
+ /// ```
3742
+ /// #![feature(slice_take)]
3743
+ ///
3744
+ /// let mut slice: &[_] = &['a', 'b', 'c'];
3745
+ /// let last = slice.take_last().unwrap();
3746
+ ///
3747
+ /// assert_eq!(slice, &['a', 'b']);
3748
+ /// assert_eq!(last, &'c');
3749
+ /// ```
3750
+ #[ inline]
3751
+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
3752
+ pub fn take_last < ' a > ( self : & mut & ' a Self ) -> Option < & ' a T > {
3753
+ let ( last, rem) = self . split_last ( ) ?;
3754
+ * self = rem;
3755
+ Some ( last)
3756
+ }
3757
+
3758
+ /// Removes the last element of the slice and returns a mutable
3759
+ /// reference to it.
3760
+ ///
3761
+ /// Returns `None` if the slice is empty.
3762
+ ///
3763
+ /// # Examples
3764
+ ///
3765
+ /// ```
3766
+ /// #![feature(slice_take)]
3767
+ ///
3768
+ /// let mut slice: &mut [_] = &mut ['a', 'b', 'c'];
3769
+ /// let last = slice.take_last_mut().unwrap();
3770
+ /// *last = 'd';
3771
+ ///
3772
+ /// assert_eq!(slice, &['a', 'b']);
3773
+ /// assert_eq!(last, &'d');
3774
+ /// ```
3775
+ #[ inline]
3776
+ #[ unstable( feature = "slice_take" , issue = "62280" ) ]
3777
+ pub fn take_last_mut < ' a > ( self : & mut & ' a mut Self ) -> Option < & ' a mut T > {
3778
+ let ( last, rem) = mem:: take ( self ) . split_last_mut ( ) ?;
3779
+ * self = rem;
3780
+ Some ( last)
3781
+ }
3520
3782
}
3521
3783
3522
3784
trait CloneFromSpec < T > {
0 commit comments