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