@@ -4540,6 +4540,121 @@ impl<T> [T] {
4540
4540
// are disjunct and in bounds.
4541
4541
unsafe { Ok ( self . get_many_unchecked_mut ( indices) ) }
4542
4542
}
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
+ }
4543
4658
}
4544
4659
4545
4660
impl < T , const N : usize > [ [ T ; N ] ] {
0 commit comments