use core::mem;
use std::io::{
Error,
ErrorKind,
Result,
};
pub enum UncheckedSlice {}
impl UncheckedSlice {
#[inline(always)]
pub const fn range_end(
len: usize,
start: usize,
count: usize,
) -> Option<usize> {
match start.checked_add(count) {
Some(end) if len >= end => Some(end),
_ => None,
}
}
#[inline(always)]
pub const fn range_fits(len: usize, start: usize, count: usize) -> bool {
Self::range_end(len, start, count).is_some()
}
#[inline]
pub fn checked_range_end(
len: usize,
start: usize,
count: usize,
message: &'static str,
) -> Result<usize> {
Self::range_end(len, start, count)
.ok_or_else(|| Error::new(ErrorKind::InvalidInput, message))
}
#[inline(always)]
pub unsafe fn read<T: Copy>(input: &[T], index: usize) -> T {
unsafe { *input.as_ptr().add(index) }
}
#[inline(always)]
pub unsafe fn write<T: Copy>(output: &mut [T], index: usize, value: T) {
unsafe {
*output.as_mut_ptr().add(index) = value;
}
}
#[inline(always)]
pub unsafe fn get<T>(input: &[T], index: usize) -> &T {
unsafe { &*input.as_ptr().add(index) }
}
#[inline(always)]
pub unsafe fn get_mut<T>(output: &mut [T], index: usize) -> &mut T {
unsafe { &mut *output.as_mut_ptr().add(index) }
}
#[inline(always)]
pub unsafe fn subslice<T>(input: &[T], start: usize, count: usize) -> &[T] {
debug_assert!(
Self::range_fits(input.len(), start, count),
"subslice range exceeds input buffer"
);
unsafe { core::slice::from_raw_parts(input.as_ptr().add(start), count) }
}
#[inline(always)]
pub unsafe fn subslice_mut<T>(
output: &mut [T],
start: usize,
count: usize,
) -> &mut [T] {
debug_assert!(
Self::range_fits(output.len(), start, count),
"subslice range exceeds output buffer"
);
unsafe {
core::slice::from_raw_parts_mut(
output.as_mut_ptr().add(start),
count,
)
}
}
#[inline(always)]
pub unsafe fn copy_nonoverlapping<T: Copy>(
source: &[T],
source_index: usize,
destination: &mut [T],
destination_index: usize,
count: usize,
) {
debug_assert!(
Self::range_fits(source.len(), source_index, count),
"unchecked source range exceeds source buffer"
);
debug_assert!(
Self::range_fits(destination.len(), destination_index, count),
"unchecked destination range exceeds destination buffer"
);
unsafe {
let src = source.as_ptr().add(source_index);
let dst = destination.as_mut_ptr().add(destination_index);
core::ptr::copy_nonoverlapping(src, dst, count);
}
}
#[inline(always)]
pub unsafe fn copy_within<T: Copy>(
buffer: &mut [T],
source_index: usize,
destination_index: usize,
count: usize,
) {
debug_assert!(
Self::range_fits(buffer.len(), source_index, count),
"unchecked source range exceeds buffer"
);
debug_assert!(
Self::range_fits(buffer.len(), destination_index, count),
"unchecked destination range exceeds buffer"
);
unsafe {
let source = buffer.as_ptr().add(source_index);
let destination = buffer.as_mut_ptr().add(destination_index);
core::ptr::copy(source, destination, count);
}
}
#[inline(always)]
pub unsafe fn read_ne_unaligned<T: Copy>(input: &[u8], index: usize) -> T {
debug_assert!(
Self::range_fits(input.len(), index, mem::size_of::<T>()),
"unchecked input range exceeds source buffer"
);
unsafe {
let src = input.as_ptr().add(index).cast::<T>();
core::ptr::read_unaligned(src)
}
}
#[inline(always)]
pub unsafe fn write_ne_unaligned<T: Copy>(
output: &mut [u8],
index: usize,
value: T,
) {
debug_assert!(
Self::range_fits(output.len(), index, mem::size_of::<T>()),
"unchecked output range exceeds destination buffer"
);
unsafe {
let dst = output.as_mut_ptr().add(index).cast::<T>();
core::ptr::write_unaligned(dst, value);
}
}
}