@@ -319,6 +319,264 @@ impl<T> [T] {
319319 if let [ .., last] = self { Some ( last) } else { None }
320320 }
321321
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+
322580 /// Returns a reference to an element or subslice depending on the type of
323581 /// index.
324582 ///
0 commit comments