use core::ops::RangeBounds;
#[inline(always)]
pub fn index_of<T>(slice: &[T], element: &T) -> Option<usize> {
index_of_ptr(slice, element as *const T)
}
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub fn index_of_ptr<T>(slice: &[T], element_ptr: *const T) -> Option<usize> {
match slice.as_ptr_range().contains(&element_ptr) {
true => Some(unsafe { element_ptr.offset_from(slice.as_ptr()) } as usize),
false => None,
}
}
pub fn contains_reference<T>(slice: &[T], element: &T) -> bool {
contains_ptr(slice, element as *const T)
}
pub fn contains_ptr<T>(slice: &[T], element_ptr: *const T) -> bool {
if slice.is_empty() {
false
} else {
let ptr_beg = slice.as_ptr();
if element_ptr < ptr_beg {
false
} else {
let ptr_end = unsafe { ptr_beg.add(slice.len() - 1) };
element_ptr <= ptr_end
}
}
}
pub fn vec_range_limits<R: RangeBounds<usize>>(range: &R, vec_len: Option<usize>) -> [usize; 2] {
use core::ops::Bound::*;
let mut begin = match range.start_bound() {
Included(&a) => a,
Excluded(a) => a + 1,
Unbounded => 0,
};
let mut end = match range.end_bound() {
Excluded(&b) => b,
Included(b) => b + 1,
Unbounded => vec_len.expect("Unbounded range without a vec_len"),
};
if end < begin {
end = begin;
}
if let Some(len) = vec_len {
if begin > len {
begin = len;
}
if end > len {
end = len;
}
}
[begin, end]
}
#[cfg(test)]
mod tests {
pub use super::*;
use alloc::vec::Vec;
#[test]
fn index_of_wrong() {
let array1 = [0, 1, 2, 3];
let array2 = [0, 1, 2];
let index1 = index_of(&array1, &array2[0]);
assert!(index1.is_none());
let index2 = index_of(&array2, &array1[0]);
assert!(index2.is_none());
}
#[test]
fn index_of_some() {
let n = 1234;
let array: Vec<_> = (0..n).collect();
for i in 0..array.len() {
let element = &array[i];
let index = index_of(&array, element);
assert_eq!(Some(i), index);
}
}
#[test]
fn contains_reference_wrong() {
let n = 1234;
let array1: Vec<_> = (0..n).collect();
let array2: Vec<_> = (0..(n - 1)).collect();
for element in array1.iter() {
assert!(!contains_reference(&array2, element));
}
for element in array2.iter() {
assert!(!contains_reference(&array1, element));
}
}
#[test]
fn contains_reference_correct() {
let n = 1111;
let array: Vec<_> = (0..n).collect();
for element in array.iter() {
assert!(contains_reference(&array, element));
}
}
}