@@ -3485,6 +3485,10 @@ impl<T> [T] {
3485
3485
/// matter, such as a sanitizer attempting to find alignment bugs. Regular code running
3486
3486
/// in a default (debug or release) execution *will* return a maximal middle part.
3487
3487
///
3488
+ /// If this behavior is not what you desire, as you don't want fallback paths for the bytes
3489
+ /// outside the aligned part, consider using [aligned_subslice] or [transmute_elements] instead,
3490
+ /// as these have stronger guarantees.
3491
+ ///
3488
3492
/// This method has no purpose when either input element `T` or output element `U` are
3489
3493
/// zero-sized and will return the original slice without splitting anything.
3490
3494
///
@@ -3547,6 +3551,10 @@ impl<T> [T] {
3547
3551
/// matter, such as a sanitizer attempting to find alignment bugs. Regular code running
3548
3552
/// in a default (debug or release) execution *will* return a maximal middle part.
3549
3553
///
3554
+ /// If this behavior is not what you desire, as you don't want fallback paths for the bytes
3555
+ /// outside the aligned part, consider using [aligned_subslice_mut] or [transmute_elements_mut]
3556
+ /// instead, as these have stronger guarantees.
3557
+ ///
3550
3558
/// This method has no purpose when either input element `T` or output element `U` are
3551
3559
/// zero-sized and will return the original slice without splitting anything.
3552
3560
///
@@ -3607,6 +3615,200 @@ impl<T> [T] {
3607
3615
}
3608
3616
}
3609
3617
3618
+ /// Get a subslice where the first element is aligned to a given alignment and the size
3619
+ /// of the slice is a multiple of the alignment.
3620
+ ///
3621
+ /// # Panics
3622
+ ///
3623
+ /// This method requires the alignment to be a multiple (larger than 1) of the alignment of
3624
+ /// the slice element's alignment.
3625
+ ///
3626
+ /// # Examples
3627
+ ///
3628
+ /// Basic usage:
3629
+ ///
3630
+ /// ```
3631
+ /// #![feature(slice_align_to_ish)]
3632
+ /// let bytes: [u8; 7] = [1, 2, 3, 4, 5, 6, 7];
3633
+ /// let ints = bytes.aligned_subslice(std::mem::align_of::<u32>());
3634
+ /// assert_eq!(ints.len(), 1);
3635
+ /// ```
3636
+ #[ must_use]
3637
+ #[ unstable( feature = "slice_align_to_ish" , issue = "none" ) ]
3638
+ #[ inline]
3639
+ pub fn aligned_subslice ( & self , align : usize ) -> & [ T ] {
3640
+ let size = crate :: mem:: size_of :: < T > ( ) ;
3641
+ assert ! (
3642
+ size < align,
3643
+ "aligned_subslice does nothing for alignments below or at the element type's alignment"
3644
+ ) ;
3645
+ assert ! (
3646
+ align % size == 0 ,
3647
+ "aligned_subslice only works for alignments that are multiples of the element's size"
3648
+ ) ;
3649
+ let offset = self . as_ptr ( ) . addr ( ) % align;
3650
+ // SAFETY: See the `align_to_mut` method for the detailed safety comment.
3651
+ let end_offset = unsafe { self . as_ptr ( ) . offset ( self . len ( ) as isize ) } . addr ( ) % align;
3652
+ let end = self . len ( ) - ( align / size - end_offset) ;
3653
+ & self [ offset..end]
3654
+ }
3655
+
3656
+ /// Get a subslice where the first element is aligned to a given alignment and the size
3657
+ /// of the slice is a multiple of the alignment.
3658
+ ///
3659
+ /// # Panics
3660
+ ///
3661
+ /// This method requires the alignment to be a multiple (larger than 1) of the alignment of
3662
+ /// the slice element's alignment.
3663
+ ///
3664
+ /// # Examples
3665
+ ///
3666
+ /// Basic usage:
3667
+ ///
3668
+ /// ```
3669
+ /// #![feature(slice_align_to_ish)]
3670
+ /// let mut bytes: [u8; 7] = [1, 2, 3, 4, 5, 6, 7];
3671
+ /// let ints = bytes.aligned_subslice_mut(std::mem::align_of::<u32>());
3672
+ /// assert_eq!(ints.len(), 1);
3673
+ /// ```
3674
+ #[ must_use]
3675
+ #[ unstable( feature = "slice_align_to_ish" , issue = "none" ) ]
3676
+ #[ inline]
3677
+ pub fn aligned_subslice_mut ( & mut self , align : usize ) -> & mut [ T ] {
3678
+ let size = crate :: mem:: size_of :: < T > ( ) ;
3679
+ assert ! (
3680
+ size < align,
3681
+ "aligned_subslice does nothing for alignments below or at the element type's alignment"
3682
+ ) ;
3683
+ assert ! (
3684
+ align % size == 0 ,
3685
+ "aligned_subslice only works for alignments that are multiples of the element's size"
3686
+ ) ;
3687
+ let offset = self . as_ptr ( ) . addr ( ) % align;
3688
+ // SAFETY: See the `align_to_mut` method for the detailed safety comment.
3689
+ let end_offset = unsafe { self . as_ptr ( ) . offset ( self . len ( ) as isize ) } . addr ( ) % align;
3690
+ let end = self . len ( ) - ( align / size - end_offset) ;
3691
+ & mut self [ offset..end]
3692
+ }
3693
+
3694
+ /// Transmute the slice elements to another type.
3695
+ ///
3696
+ /// If the target element type is smaller than the source element type, the
3697
+ /// returned slice will have multiple elements per element of the original slice.
3698
+ ///
3699
+ /// Cannot be used to go to an element type with higher alignment requirements.
3700
+ /// Use `aligned_subslice` for that instead.
3701
+ ///
3702
+ /// # Panics
3703
+ ///
3704
+ /// The element sizes and the slice length must be such that all elements of the source
3705
+ /// slice fit exactly into a slice of the destination element type. Resize your input slice
3706
+ /// before invoking `transmute_elements` to uphold this checked requirement.
3707
+ ///
3708
+ /// # Safety
3709
+ ///
3710
+ /// This method is essentially a `transmute` between different elements, and even from
3711
+ /// multiple elements into a single one or vice versa, so all the usual caveats
3712
+ /// pertaining to `transmute::<T, U>` also apply here.
3713
+ ///
3714
+ /// # Examples
3715
+ ///
3716
+ /// Basic usage:
3717
+ ///
3718
+ /// ```
3719
+ /// unsafe {
3720
+ /// let ints: [u32; 2] = [1, 2];
3721
+ /// let smaller_ints = ints.transmute_elements::<u16>();
3722
+ /// assert_eq!(smaller_ints.len(), 4);
3723
+ /// }
3724
+ /// ```
3725
+ #[ must_use]
3726
+ #[ unstable( feature = "slice_align_to_ish" , issue = "none" ) ]
3727
+ #[ track_caller]
3728
+ pub const unsafe fn transmute_elements < U > ( & self ) -> & [ U ] {
3729
+ const {
3730
+ let align_u = crate :: mem:: align_of :: < U > ( ) ;
3731
+ let align_t = crate :: mem:: align_of :: < T > ( ) ;
3732
+ assert ! ( align_u <= align_t, "use `aligned_subslice` instead" ) ;
3733
+ } ;
3734
+ let size_u = crate :: mem:: size_of :: < U > ( ) ;
3735
+ let size_t = crate :: mem:: size_of :: < T > ( ) ;
3736
+ if size_u > size_t {
3737
+ assert ! (
3738
+ self . len( ) * size_u % size_t == 0 ,
3739
+ "input slice does not fit exactly into a slice of the output element type"
3740
+ ) ;
3741
+ } else {
3742
+ assert ! (
3743
+ self . len( ) * size_t % size_u == 0 ,
3744
+ "input slice does not fit exactly into a slice of the output element type"
3745
+ ) ;
3746
+ }
3747
+ // SAFETY: The size of the slice is such that with the new element size, all new
3748
+ // elements are still within the bounds of the original slice. The change in element
3749
+ // type is something the caller needs to make sure is sound.
3750
+ unsafe { from_raw_parts ( self . as_ptr ( ) as * const _ , self . len ( ) * size_t / size_u) }
3751
+ }
3752
+
3753
+ /// Transmute the slice elements to another type.
3754
+ ///
3755
+ /// If the target element type is smaller than the source element type, the
3756
+ /// returned slice will have multiple elements per element of the original slice.
3757
+ ///
3758
+ /// Cannot be used to go to an element type with higher alignment requirements.
3759
+ /// Use `aligned_subslice_mut` for that instead.
3760
+ ///
3761
+ /// # Panics
3762
+ ///
3763
+ /// The element sizes and the slice length must be such that all elements of the source
3764
+ /// slice fit exactly into a slice of the destination element type. Resize your input slice
3765
+ /// before invoking `transmute_elements_mut` to uphold this checked requirement.
3766
+ ///
3767
+ /// # Safety
3768
+ ///
3769
+ /// This method is essentially a `transmute` between different elements, and even from
3770
+ /// multiple elements into a single one or vice versa, so all the usual caveats
3771
+ /// pertaining to `transmute::<T, U>` also apply here.
3772
+ ///
3773
+ /// # Examples
3774
+ ///
3775
+ /// Basic usage:
3776
+ ///
3777
+ /// ```
3778
+ /// unsafe {
3779
+ /// let mut ints: [u32; 2] = [1, 2];
3780
+ /// let smaller_ints = ints.transmute_elements_mut::<u16>();
3781
+ /// assert_eq!(smaller_ints.len(), 4);
3782
+ /// }
3783
+ /// ```
3784
+ #[ must_use]
3785
+ #[ unstable( feature = "slice_align_to_ish" , issue = "none" ) ]
3786
+ #[ track_caller]
3787
+ pub const unsafe fn transmute_elements_mut < U > ( & mut self ) -> & mut [ U ] {
3788
+ const {
3789
+ let align_u = crate :: mem:: align_of :: < U > ( ) ;
3790
+ let align_t = crate :: mem:: align_of :: < T > ( ) ;
3791
+ assert ! ( align_u <= align_t, "use `aligned_subslice_mut` instead" ) ;
3792
+ } ;
3793
+ let size_u = crate :: mem:: size_of :: < U > ( ) ;
3794
+ let size_t = crate :: mem:: size_of :: < T > ( ) ;
3795
+ if size_u > size_t {
3796
+ assert ! (
3797
+ self . len( ) * size_u % size_t == 0 ,
3798
+ "input slice does not fit exactly into a slice of the output element type"
3799
+ ) ;
3800
+ } else {
3801
+ assert ! (
3802
+ self . len( ) * size_t % size_u == 0 ,
3803
+ "input slice does not fit exactly into a slice of the output element type"
3804
+ ) ;
3805
+ }
3806
+ // SAFETY: The size of the slice is such that with the new element size, all new
3807
+ // elements are still within the bounds of the original slice. The change in element
3808
+ // type is something the caller needs to make sure is sound.
3809
+ unsafe { from_raw_parts_mut ( self . as_mut_ptr ( ) as * mut _ , self . len ( ) * size_t / size_u) }
3810
+ }
3811
+
3610
3812
/// Split a slice into a prefix, a middle of aligned SIMD types, and a suffix.
3611
3813
///
3612
3814
/// This is a safe wrapper around [`slice::align_to`], so has the same weak
0 commit comments