@@ -12,7 +12,7 @@ use crate::cmp::Ordering::{self, Equal, Greater, Less};
12
12
use crate :: marker:: Copy ;
13
13
use crate :: mem;
14
14
use crate :: num:: NonZeroUsize ;
15
- use crate :: ops:: { FnMut , Range , RangeBounds } ;
15
+ use crate :: ops:: { Bound , FnMut , OneSidedRange , Range , RangeBounds } ;
16
16
use crate :: option:: Option ;
17
17
use crate :: option:: Option :: { None , Some } ;
18
18
use crate :: ptr;
@@ -73,6 +73,24 @@ pub use sort::heapsort;
73
73
#[ stable( feature = "slice_get_slice" , since = "1.28.0" ) ]
74
74
pub use index:: SliceIndex ;
75
75
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
+
76
94
#[ lang = "slice" ]
77
95
#[ cfg( not( test) ) ]
78
96
impl < T > [ T ] {
@@ -3169,6 +3187,227 @@ impl<T> [T] {
3169
3187
3170
3188
left
3171
3189
}
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
+ }
3172
3411
}
3173
3412
3174
3413
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
0 commit comments