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

`` +

/// .windows().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> {

`

``

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]] {

`