Add elem_offset and related methods · model-checking/verify-rust-std@0374ea2 (original) (raw)
`@@ -4540,6 +4540,121 @@ impl [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()
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 {
`
``
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::() != 0 {
`
``
4597
`+
return None;
`
``
4598
`+
}
`
``
4599
+
``
4600
`+
let offset = byte_offset / mem::size_of::();
`
``
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
`` +
``
``
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> {
`
``
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::() != 0 {
`
``
4650
`+
return None;
`
``
4651
`+
}
`
``
4652
+
``
4653
`+
let start = byte_start / core::mem::size_of::();
`
``
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]] {
`