@@ -319,6 +319,264 @@ impl<T> [T] {
319
319
if let [ .., last] = self { Some ( last) } else { None }
320
320
}
321
321
322
+ /// Returns the first `N` elements of the slice, or `None` if it has fewer than `N` elements.
323
+ ///
324
+ /// # Examples
325
+ ///
326
+ /// ```
327
+ /// #![feature(slice_first_last_chunk)]
328
+ ///
329
+ /// let u = [10, 40, 30];
330
+ /// assert_eq!(Some(&[10, 40]), u.first_chunk::<2>());
331
+ ///
332
+ /// let v: &[i32] = &[10];
333
+ /// assert_eq!(None, v.first_chunk::<2>());
334
+ ///
335
+ /// let w: &[i32] = &[];
336
+ /// assert_eq!(Some(&[]), w.first_chunk::<0>());
337
+ /// ```
338
+ #[ unstable( feature = "slice_first_last_chunk" , issue = "111774" ) ]
339
+ #[ rustc_const_unstable( feature = "slice_first_last_chunk" , issue = "111774" ) ]
340
+ #[ inline]
341
+ pub const fn first_chunk < const N : usize > ( & self ) -> Option < & [ T ; N ] > {
342
+ if self . len ( ) < N {
343
+ None
344
+ } else {
345
+ // SAFETY: We explicitly check for the correct number of elements,
346
+ // and do not let the reference outlive the slice.
347
+ Some ( unsafe { & * ( self . as_ptr ( ) as * const [ T ; N ] ) } )
348
+ }
349
+ }
350
+
351
+ /// Returns a mutable reference to the first `N` elements of the slice,
352
+ /// or `None` if it has fewer than `N` elements.
353
+ ///
354
+ /// # Examples
355
+ ///
356
+ /// ```
357
+ /// #![feature(slice_first_last_chunk)]
358
+ ///
359
+ /// let x = &mut [0, 1, 2];
360
+ ///
361
+ /// if let Some(first) = x.first_chunk_mut::<2>() {
362
+ /// first[0] = 5;
363
+ /// first[1] = 4;
364
+ /// }
365
+ /// assert_eq!(x, &[5, 4, 2]);
366
+ /// ```
367
+ #[ unstable( feature = "slice_first_last_chunk" , issue = "111774" ) ]
368
+ #[ rustc_const_unstable( feature = "slice_first_last_chunk" , issue = "111774" ) ]
369
+ #[ inline]
370
+ pub const fn first_chunk_mut < const N : usize > ( & mut self ) -> Option < & mut [ T ; N ] > {
371
+ if self . len ( ) < N {
372
+ None
373
+ } else {
374
+ // SAFETY: We explicitly check for the correct number of elements,
375
+ // do not let the reference outlive the slice,
376
+ // and require exclusive access to the entire slice to mutate the chunk.
377
+ Some ( unsafe { & mut * ( self . as_mut_ptr ( ) as * mut [ T ; N ] ) } )
378
+ }
379
+ }
380
+
381
+ /// Returns the first `N` elements of the slice and the remainder,
382
+ /// or `None` if it has fewer than `N` elements.
383
+ ///
384
+ /// # Examples
385
+ ///
386
+ /// ```
387
+ /// #![feature(slice_first_last_chunk)]
388
+ ///
389
+ /// let x = &[0, 1, 2];
390
+ ///
391
+ /// if let Some((first, elements)) = x.split_first_chunk::<2>() {
392
+ /// assert_eq!(first, &[0, 1]);
393
+ /// assert_eq!(elements, &[2]);
394
+ /// }
395
+ /// ```
396
+ #[ unstable( feature = "slice_first_last_chunk" , issue = "111774" ) ]
397
+ #[ rustc_const_unstable( feature = "slice_first_last_chunk" , issue = "111774" ) ]
398
+ #[ inline]
399
+ pub const fn split_first_chunk < const N : usize > ( & self ) -> Option < ( & [ T ; N ] , & [ T ] ) > {
400
+ if self . len ( ) < N {
401
+ None
402
+ } else {
403
+ // SAFETY: We manually verified the bounds of the split.
404
+ let ( first, tail) = unsafe { self . split_at_unchecked ( N ) } ;
405
+
406
+ // SAFETY: We explicitly check for the correct number of elements,
407
+ // and do not let the references outlive the slice.
408
+ Some ( ( unsafe { & * ( first. as_ptr ( ) as * const [ T ; N ] ) } , tail) )
409
+ }
410
+ }
411
+
412
+ /// Returns a mutable reference to the first `N` elements of the slice and the remainder,
413
+ /// or `None` if it has fewer than `N` elements.
414
+ ///
415
+ /// # Examples
416
+ ///
417
+ /// ```
418
+ /// #![feature(slice_first_last_chunk)]
419
+ ///
420
+ /// let x = &mut [0, 1, 2];
421
+ ///
422
+ /// if let Some((first, elements)) = x.split_first_chunk_mut::<2>() {
423
+ /// first[0] = 3;
424
+ /// first[1] = 4;
425
+ /// elements[0] = 5;
426
+ /// }
427
+ /// assert_eq!(x, &[3, 4, 5]);
428
+ /// ```
429
+ #[ unstable( feature = "slice_first_last_chunk" , issue = "111774" ) ]
430
+ #[ rustc_const_unstable( feature = "slice_first_last_chunk" , issue = "111774" ) ]
431
+ #[ inline]
432
+ pub const fn split_first_chunk_mut < const N : usize > (
433
+ & mut self ,
434
+ ) -> Option < ( & mut [ T ; N ] , & mut [ T ] ) > {
435
+ if self . len ( ) < N {
436
+ None
437
+ } else {
438
+ // SAFETY: We manually verified the bounds of the split.
439
+ let ( first, tail) = unsafe { self . split_at_mut_unchecked ( N ) } ;
440
+
441
+ // SAFETY: We explicitly check for the correct number of elements,
442
+ // do not let the reference outlive the slice,
443
+ // and enforce exclusive mutability of the chunk by the split.
444
+ Some ( ( unsafe { & mut * ( first. as_mut_ptr ( ) as * mut [ T ; N ] ) } , tail) )
445
+ }
446
+ }
447
+
448
+ /// Returns the last `N` elements of the slice and the remainder,
449
+ /// or `None` if it has fewer than `N` elements.
450
+ ///
451
+ /// # Examples
452
+ ///
453
+ /// ```
454
+ /// #![feature(slice_first_last_chunk)]
455
+ ///
456
+ /// let x = &[0, 1, 2];
457
+ ///
458
+ /// if let Some((last, elements)) = x.split_last_chunk::<2>() {
459
+ /// assert_eq!(last, &[1, 2]);
460
+ /// assert_eq!(elements, &[0]);
461
+ /// }
462
+ /// ```
463
+ #[ unstable( feature = "slice_first_last_chunk" , issue = "111774" ) ]
464
+ #[ rustc_const_unstable( feature = "slice_first_last_chunk" , issue = "111774" ) ]
465
+ #[ inline]
466
+ pub const fn split_last_chunk < const N : usize > ( & self ) -> Option < ( & [ T ; N ] , & [ T ] ) > {
467
+ if self . len ( ) < N {
468
+ None
469
+ } else {
470
+ // SAFETY: We manually verified the bounds of the split.
471
+ let ( init, last) = unsafe { self . split_at_unchecked ( self . len ( ) - N ) } ;
472
+
473
+ // SAFETY: We explicitly check for the correct number of elements,
474
+ // and do not let the references outlive the slice.
475
+ Some ( ( unsafe { & * ( last. as_ptr ( ) as * const [ T ; N ] ) } , init) )
476
+ }
477
+ }
478
+
479
+ /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty.
480
+ ///
481
+ /// # Examples
482
+ ///
483
+ /// ```
484
+ /// #![feature(slice_first_last_chunk)]
485
+ ///
486
+ /// let x = &mut [0, 1, 2];
487
+ ///
488
+ /// if let Some((last, elements)) = x.split_last_chunk_mut::<2>() {
489
+ /// last[0] = 3;
490
+ /// last[1] = 4;
491
+ /// elements[0] = 5;
492
+ /// }
493
+ /// assert_eq!(x, &[5, 3, 4]);
494
+ /// ```
495
+ #[ unstable( feature = "slice_first_last_chunk" , issue = "111774" ) ]
496
+ #[ rustc_const_unstable( feature = "slice_first_last_chunk" , issue = "111774" ) ]
497
+ #[ inline]
498
+ pub const fn split_last_chunk_mut < const N : usize > (
499
+ & mut self ,
500
+ ) -> Option < ( & mut [ T ; N ] , & mut [ T ] ) > {
501
+ if self . len ( ) < N {
502
+ None
503
+ } else {
504
+ // SAFETY: We manually verified the bounds of the split.
505
+ let ( init, last) = unsafe { self . split_at_mut_unchecked ( self . len ( ) - N ) } ;
506
+
507
+ // SAFETY: We explicitly check for the correct number of elements,
508
+ // do not let the reference outlive the slice,
509
+ // and enforce exclusive mutability of the chunk by the split.
510
+ Some ( ( unsafe { & mut * ( last. as_mut_ptr ( ) as * mut [ T ; N ] ) } , init) )
511
+ }
512
+ }
513
+
514
+ /// Returns the last element of the slice, or `None` if it is empty.
515
+ ///
516
+ /// # Examples
517
+ ///
518
+ /// ```
519
+ /// #![feature(slice_first_last_chunk)]
520
+ ///
521
+ /// let u = [10, 40, 30];
522
+ /// assert_eq!(Some(&[40, 30]), u.last_chunk::<2>());
523
+ ///
524
+ /// let v: &[i32] = &[10];
525
+ /// assert_eq!(None, v.last_chunk::<2>());
526
+ ///
527
+ /// let w: &[i32] = &[];
528
+ /// assert_eq!(Some(&[]), w.last_chunk::<0>());
529
+ /// ```
530
+ #[ unstable( feature = "slice_first_last_chunk" , issue = "111774" ) ]
531
+ #[ rustc_const_unstable( feature = "slice_first_last_chunk" , issue = "111774" ) ]
532
+ #[ inline]
533
+ pub const fn last_chunk < const N : usize > ( & self ) -> Option < & [ T ; N ] > {
534
+ if self . len ( ) < N {
535
+ None
536
+ } else {
537
+ // SAFETY: We manually verified the bounds of the slice.
538
+ // FIXME: Without const traits, we need this instead of `get_unchecked`.
539
+ let last = unsafe { self . split_at_unchecked ( self . len ( ) - N ) . 1 } ;
540
+
541
+ // SAFETY: We explicitly check for the correct number of elements,
542
+ // and do not let the references outlive the slice.
543
+ Some ( unsafe { & * ( last. as_ptr ( ) as * const [ T ; N ] ) } )
544
+ }
545
+ }
546
+
547
+ /// Returns a mutable pointer to the last item in the slice.
548
+ ///
549
+ /// # Examples
550
+ ///
551
+ /// ```
552
+ /// #![feature(slice_first_last_chunk)]
553
+ ///
554
+ /// let x = &mut [0, 1, 2];
555
+ ///
556
+ /// if let Some(last) = x.last_chunk_mut::<2>() {
557
+ /// last[0] = 10;
558
+ /// last[1] = 20;
559
+ /// }
560
+ /// assert_eq!(x, &[0, 10, 20]);
561
+ /// ```
562
+ #[ unstable( feature = "slice_first_last_chunk" , issue = "111774" ) ]
563
+ #[ rustc_const_unstable( feature = "slice_first_last_chunk" , issue = "111774" ) ]
564
+ #[ inline]
565
+ pub const fn last_chunk_mut < const N : usize > ( & mut self ) -> Option < & mut [ T ; N ] > {
566
+ if self . len ( ) < N {
567
+ None
568
+ } else {
569
+ // SAFETY: We manually verified the bounds of the slice.
570
+ // FIXME: Without const traits, we need this instead of `get_unchecked`.
571
+ let last = unsafe { self . split_at_mut_unchecked ( self . len ( ) - N ) . 1 } ;
572
+
573
+ // SAFETY: We explicitly check for the correct number of elements,
574
+ // do not let the reference outlive the slice,
575
+ // and require exclusive access to the entire slice to mutate the chunk.
576
+ Some ( unsafe { & mut * ( last. as_mut_ptr ( ) as * mut [ T ; N ] ) } )
577
+ }
578
+ }
579
+
322
580
/// Returns a reference to an element or subslice depending on the type of
323
581
/// index.
324
582
///
0 commit comments