Add elem_offset and related methods · model-checking/verify-rust-std@0374ea2

@@ -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

}

4544465945454660

impl<T, const N: usize> [[T; N]] {