@@ -4522,6 +4522,121 @@ impl<T> [T] {
45224522 // are disjunct and in bounds.
45234523 unsafe { Ok ( self . get_many_unchecked_mut ( indices) ) }
45244524 }
4525+
4526+ /// Returns the index that an element reference points to.
4527+ ///
4528+ /// Returns `None` if `element` does not point within the slice or if it points between elements.
4529+ ///
4530+ /// This method is useful for extending slice iterators like [`slice::split`].
4531+ ///
4532+ /// Note that this uses pointer arithmetic and **does not compare elements**.
4533+ /// To find the index of an element via comparison, use
4534+ /// [`.iter().position()`](crate::iter::Iterator::position) instead.
4535+ ///
4536+ /// # Panics
4537+ /// Panics if `T` is zero-sized.
4538+ ///
4539+ /// # Examples
4540+ /// Basic usage:
4541+ /// ```
4542+ /// #![feature(substr_range)]
4543+ ///
4544+ /// let nums: &[u32] = &[1, 7, 1, 1];
4545+ /// let num = &nums[2];
4546+ ///
4547+ /// assert_eq!(num, &1);
4548+ /// assert_eq!(nums.elem_offset(num), Some(2));
4549+ /// ```
4550+ /// Returning `None` with an in-between element:
4551+ /// ```
4552+ /// #![feature(substr_range)]
4553+ ///
4554+ /// let arr: &[[u32; 2]] = &[[0, 1], [2, 3]];
4555+ /// let flat_arr: &[u32] = arr.as_flattened();
4556+ ///
4557+ /// let ok_elm: &[u32; 2] = flat_arr[0..2].try_into().unwrap();
4558+ /// let weird_elm: &[u32; 2] = flat_arr[1..3].try_into().unwrap();
4559+ ///
4560+ /// assert_eq!(ok_elm, &[0, 1]);
4561+ /// assert_eq!(weird_elm, &[1, 2]);
4562+ ///
4563+ /// assert_eq!(arr.elem_offset(ok_elm), Some(0)); // Points to element 0
4564+ /// assert_eq!(arr.elem_offset(weird_elm), None); // Points between element 0 and 1
4565+ /// ```
4566+ #[ must_use]
4567+ #[ unstable( feature = "substr_range" , issue = "126769" ) ]
4568+ pub fn elem_offset ( & self , element : & T ) -> Option < usize > {
4569+ if T :: IS_ZST {
4570+ panic ! ( "elements are zero-sized" ) ;
4571+ }
4572+
4573+ let self_start = self . as_ptr ( ) as usize ;
4574+ let elem_start = element as * const T as usize ;
4575+
4576+ let byte_offset = elem_start. wrapping_sub ( self_start) ;
4577+
4578+ if byte_offset % mem:: size_of :: < T > ( ) != 0 {
4579+ return None ;
4580+ }
4581+
4582+ let offset = byte_offset / mem:: size_of :: < T > ( ) ;
4583+
4584+ if offset < self . len ( ) { Some ( offset) } else { None }
4585+ }
4586+
4587+ /// Returns the range of indices that a subslice points to.
4588+ ///
4589+ /// Returns `None` if `subslice` does not point within the slice or if it points between elements.
4590+ ///
4591+ /// This method **does not compare elements**. Instead, this method finds the location in the slice that
4592+ /// `subslice` was obtained from. To find the index of a subslice via comparison, instead use
4593+ /// [`.windows()`](slice::windows)[`.position()`](crate::iter::Iterator::position).
4594+ ///
4595+ /// This method is useful for extending slice iterators like [`slice::split`].
4596+ ///
4597+ /// Note that this may return a false positive (either `Some(0..0)` or `Some(self.len()..self.len())`)
4598+ /// if `subslice` has a length of zero and points to the beginning or end of another, separate, slice.
4599+ ///
4600+ /// # Panics
4601+ /// Panics if `T` is zero-sized.
4602+ ///
4603+ /// # Examples
4604+ /// Basic usage:
4605+ /// ```
4606+ /// #![feature(substr_range)]
4607+ ///
4608+ /// let nums = &[0, 5, 10, 0, 0, 5];
4609+ ///
4610+ /// let mut iter = nums
4611+ /// .split(|t| *t == 0)
4612+ /// .map(|n| nums.subslice_range(n).unwrap());
4613+ ///
4614+ /// assert_eq!(iter.next(), Some(0..0));
4615+ /// assert_eq!(iter.next(), Some(1..3));
4616+ /// assert_eq!(iter.next(), Some(4..4));
4617+ /// assert_eq!(iter.next(), Some(5..6));
4618+ /// ```
4619+ #[ must_use]
4620+ #[ unstable( feature = "substr_range" , issue = "126769" ) ]
4621+ pub fn subslice_range ( & self , subslice : & [ T ] ) -> Option < Range < usize > > {
4622+ if T :: IS_ZST {
4623+ panic ! ( "elements are zero-sized" ) ;
4624+ }
4625+
4626+ let self_start = self . as_ptr ( ) as usize ;
4627+ let subslice_start = subslice. as_ptr ( ) as usize ;
4628+
4629+ let byte_start = subslice_start. wrapping_sub ( self_start) ;
4630+
4631+ if byte_start % core:: mem:: size_of :: < T > ( ) != 0 {
4632+ return None ;
4633+ }
4634+
4635+ let start = byte_start / core:: mem:: size_of :: < T > ( ) ;
4636+ let end = start. wrapping_add ( subslice. len ( ) ) ;
4637+
4638+ if start <= self . len ( ) && end <= self . len ( ) { Some ( start..end) } else { None }
4639+ }
45254640}
45264641
45274642impl < T , const N : usize > [ [ T ; N ] ] {
0 commit comments