#![allow(dead_code)]
#![cfg(not(tarpaulin_include))]
use crate::{
index::BitMask,
pointer::BitPtr,
store::BitStore,
};
use core::{
ops::{
Bound,
Range,
RangeBounds,
},
ptr::{
self,
NonNull,
},
};
use tap::pipe::Pipe;
#[inline(always)]
#[cfg(not(tarpaulin_include))]
pub fn accessor<T>(x: &T) -> &T::Access
where T: BitStore {
unsafe { &*(x as *const T as *const T::Access) }
}
#[inline(always)]
#[cfg(not(tarpaulin_include))]
pub fn alias_mask<T>(
x: BitMask<T::Mem>,
) -> BitMask<<T::Alias as BitStore>::Mem>
where T: BitStore {
unsafe { *(&x as *const _ as *const _) }
}
#[inline(always)]
#[cfg(not(tarpaulin_include))]
pub fn alias_mem<T>(x: T::Mem) -> <T::Alias as BitStore>::Mem
where T: BitStore {
unsafe { *(&x as *const _ as *const _) }
}
#[inline(always)]
#[cfg(not(tarpaulin_include))]
pub fn load_aliased_local<T>(x: &T::Alias) -> T::Mem
where T: BitStore {
x.load_value().pipe(remove_alias::<T>)
}
#[inline(always)]
#[cfg(not(tarpaulin_include))]
pub fn mem_mut<T>(x: &mut T) -> &mut T::Mem
where T: BitStore {
unsafe { &mut *(x as *mut _ as *mut _) }
}
#[inline(always)]
#[cfg(not(tarpaulin_include))]
pub fn remove_alias<T>(x: <<T as BitStore>::Alias as BitStore>::Mem) -> T::Mem
where T: BitStore {
unsafe { *(&x as *const _ as *const _) }
}
#[inline(always)]
#[cfg(not(tarpaulin_include))]
pub fn remove_bitptr_alias<T>(x: BitPtr<T::Alias>) -> BitPtr<T>
where T: BitStore {
unsafe { *(&x as *const _ as *const _) }
}
#[inline(always)]
#[cfg(not(tarpaulin_include))]
pub fn remove_mem<T>(x: T::Mem) -> T
where T: BitStore {
unsafe { ptr::read(&x as *const T::Mem as *const T) }
}
#[inline(always)]
#[cfg(not(tarpaulin_include))]
pub fn nonnull_slice_to_base<T>(mut nn_slice: NonNull<[T]>) -> NonNull<T> {
unsafe { nn_slice.as_mut() }
.pipe(<[T]>::as_mut_ptr)
.pipe(|p| unsafe { NonNull::new_unchecked(p) })
}
#[inline]
pub fn normalize_range<R>(bounds: R, end: usize) -> Range<usize>
where R: RangeBounds<usize> {
let min = match bounds.start_bound() {
Bound::Included(&n) => n,
Bound::Excluded(&n) => n + 1,
Bound::Unbounded => 0,
};
let max = match bounds.end_bound() {
Bound::Included(&n) => n + 1,
Bound::Excluded(&n) => n,
Bound::Unbounded => end,
};
min .. max
}
#[inline]
pub fn assert_range(range: Range<usize>, end: impl Into<Option<usize>>) {
if range.start > range.end {
panic!(
"Malformed range: `{} .. {}` must run from lower to higher",
range.start, range.end
);
}
if let Some(end) = end.into() {
if range.end > end {
panic!(
"Range out of bounds: `{} .. {}` must not exceed `{}`",
range.start, range.end, end
);
}
}
}
#[cfg(all(test, feature = "std"))]
mod tests {
use super::*;
use std::panic::catch_unwind;
#[test]
fn check_range_asserts() {
assert!(catch_unwind(|| assert_range(7 .. 2, None)).is_err());
assert!(catch_unwind(|| assert_range(0 .. 8, 4)).is_err());
}
}