#![doc(html_root_url = "https://docs.rs/slice-of-array/0.3.2")]
#![cfg_attr(not(feature = "std"), no_std)]
use core::slice;
pub mod prelude {
pub use super::SliceFlatExt;
pub use super::SliceNestExt;
pub use super::SliceArrayExt;
}
pub unsafe trait IsSliceomorphic: Sized {
type Element;
const LEN: usize;
}
unsafe impl<T, const N: usize> IsSliceomorphic for [T; N] {
type Element = T;
const LEN: usize = N;
}
fn validate_alignment_and_size<V: IsSliceomorphic>() {
use core::mem::{align_of, size_of};
assert_eq!(
align_of::<V::Element>(),
align_of::<V>(),
);
assert_eq!(
V::LEN * size_of::<V::Element>(),
size_of::<V>(),
);
}
pub trait SliceFlatExt<T> {
fn flat(&self) -> &[T];
fn flat_mut(&mut self) -> &mut [T];
}
pub trait SliceNestExt<T> {
fn nest<V: IsSliceomorphic<Element=T>>(&self) -> &[V];
fn nest_mut<V: IsSliceomorphic<Element=T>>(&mut self) -> &mut [V];
}
pub trait SliceArrayExt<T> {
fn as_array<V: IsSliceomorphic<Element=T>>(&self) -> &V;
fn as_mut_array<V: IsSliceomorphic<Element=T>>(&mut self) -> &mut V;
fn to_array<V: IsSliceomorphic<Element=T>>(&self) -> V where V: Clone
{ self.as_array::<V>().clone() }
}
impl<V: IsSliceomorphic> SliceFlatExt<V::Element> for [V] {
fn flat(&self) -> &[V::Element] {
let new_len = checked_compute_flattened_len::<V>(self.len());
unsafe {
slice::from_raw_parts(
self.as_ptr() as *const _,
new_len,
)
}
}
fn flat_mut(&mut self) -> &mut [V::Element] {
let new_len = checked_compute_flattened_len::<V>(self.len());
unsafe {
slice::from_raw_parts_mut(
self.as_mut_ptr() as *mut _,
new_len,
)
}
}
}
#[inline(always)]
fn checked_compute_flattened_len<V: IsSliceomorphic>(len: usize) -> usize {
validate_alignment_and_size::<V>();
if core::mem::size_of::<V::Element>() == 0 {
usize::checked_mul(len, V::LEN)
.expect("overflow when computing length of flattened array")
} else {
len * V::LEN
}
}
impl<T> SliceNestExt<T> for [T] {
fn nest<V: IsSliceomorphic<Element=T>>(&self) -> &[V] {
let new_len = checked_compute_nested_len::<V>(self.len(), "&");
unsafe { slice::from_raw_parts(
self.as_ptr() as *const _,
new_len,
)}
}
fn nest_mut<V: IsSliceomorphic<Element=T>>(&mut self) -> &mut [V] {
let new_len = checked_compute_nested_len::<V>(self.len(), "&mut ");
unsafe { slice::from_raw_parts_mut(
self.as_mut_ptr() as *mut _,
new_len,
)}
}
}
#[inline(always)]
fn checked_compute_nested_len<V: IsSliceomorphic>(len: usize, prefix: &str) -> usize {
validate_alignment_and_size::<V>();
assert_ne!(
0, V::LEN,
"cannot nest arrays of length 0",
);
assert_eq!(
0, len % V::LEN,
"cannot view slice of length {} as {}[[_; {}]]",
len, prefix, V::LEN,
);
len / V::LEN
}
impl<T> SliceArrayExt<T> for [T] {
fn as_array<V: IsSliceomorphic<Element=T>>(&self) -> &V {
validate_as_array_assumptions::<V>(self.len(), "&");
unsafe { (self.as_ptr() as *const V).as_ref().unwrap() }
}
fn as_mut_array<V: IsSliceomorphic<Element=T>>(&mut self) -> &mut V {
validate_as_array_assumptions::<V>(self.len(), "&mut ");
unsafe { (self.as_mut_ptr() as *mut V).as_mut().unwrap() }
}
}
#[inline(always)]
fn validate_as_array_assumptions<V: IsSliceomorphic>(len: usize, prefix: &str) {
validate_alignment_and_size::<V>();
assert_eq!(
len, V::LEN,
"cannot view slice of length {} as {}[_; {}]",
len, prefix, V::LEN,
);
}
#[cfg(test)]
mod tests {
pub use super::prelude::*;
#[test]
fn inference_lattice() {
let v: &mut [()] = &mut [(); 9];
{ let _: &[[(); 3]; 3] = v.nest().as_array(); }
{ let _: &[[[(); 3]; 3]] = v.nest().nest(); }
{ let _: &mut [[(); 3]; 3] = v.nest_mut().as_mut_array(); }
{ let _: &mut [[[(); 3]; 3]] = v.nest_mut().nest_mut(); }
{ let _: [[(); 3]; 3] = v.nest().to_array(); }
#[cfg(feature = "std")]
{ let _: Vec<[(); 3]> = v.nest().to_vec(); }
}
#[test]
fn test_flat_zst_and_non_zst() {
let v: &mut [_] = &mut [[(); 234]; 456];
assert_eq!(v.flat(), &[(); 234*456] as &[()]);
assert_eq!(v.flat_mut(), &[(); 234*456] as &[()]);
let v: &mut [_] = &mut [[1; 23]; 45];
assert_eq!(v.flat(), &[1; 23*45] as &[i32]);
assert_eq!(v.flat_mut(), &[1; 23*45] as &[i32]);
}
#[test]
fn test_flat_zero() {
let v: &mut [[(); 0]] = &mut [[(); 0]; 6];
assert_eq!(v.flat(), &[] as &[()]);
assert_eq!(v.flat_mut(), &[] as &[()]);
}
#[test]
fn test_array_zero() {
let v: &mut [[(); 0]] = &mut [[], [], [], []];
assert_eq!(v.flat(), &[] as &[()]);
assert_eq!(v.flat_mut(), &[] as &[()]);
}
mod failures {
use super::super::*;
const BIG_1: usize = 0x30;
const BIG_2: usize = usize::MAX >> 4;
#[test]
#[should_panic(expected = "overflow when computing length")]
fn flat_zst_overflow() {
let v: &[_] = &[[(); BIG_1]; BIG_2];
let _: &[()] = v.flat();
}
#[test]
#[should_panic(expected = "overflow when computing length")]
fn flat_mut_zst_overflow() {
let v: &mut [_] = &mut [[(); BIG_1]; BIG_2];
let _: &mut [()] = v.flat_mut();
}
#[test]
#[should_panic(expected = "cannot view slice of length 8")]
fn nest_not_multiple() {
let v: &[_] = &[(); 8];
let _: &[[(); 3]] = v.nest();
}
#[test]
#[should_panic(expected = "cannot view slice of length 8")]
fn nest_mut_not_multiple() {
let v: &mut [_] = &mut [(); 8];
let _: &mut [[(); 3]] = v.nest_mut();
}
#[test]
#[should_panic(expected = "cannot nest arrays of length 0")]
fn nest_zero() {
let v: &[_] = &[(); 0];
let _: &[[(); 0]] = v.nest();
}
#[test]
#[should_panic(expected = "cannot nest arrays of length 0")]
fn nest_mut_zero() {
let v: &mut [_] = &mut [(); 0];
let _: &mut [[(); 0]] = v.nest_mut();
}
#[test]
#[should_panic(expected = "cannot view slice of length 1")]
fn as_array_too_small() {
let v: &[_] = &[(); 1];
let _: &[(); 3] = v.as_array();
}
#[test]
#[should_panic(expected = "cannot view slice of length 6")]
fn as_array_too_large() {
let v: &[_] = &[(); 6];
let _: &[(); 3] = v.as_array();
}
#[test]
#[should_panic(expected = "cannot view slice of length 6")]
fn as_array_bad_zero() {
let v: &[_] = &[(); 6];
let _: &[(); 0] = v.as_array();
}
#[test]
#[should_panic(expected = "cannot view slice of length 1")]
fn as_mut_array_too_small() {
let v: &mut [_] = &mut [(); 1];
let _: &mut [(); 3] = v.as_mut_array();
}
#[test]
#[should_panic(expected = "cannot view slice of length 6")]
fn as_mut_array_too_large() {
let v: &mut [_] = &mut [(); 6];
let _: &mut [(); 3] = v.as_mut_array();
}
#[test]
#[should_panic(expected = "cannot view slice of length 6")]
fn as_mut_array_bad_zero() {
let v: &mut [_] = &mut [(); 6];
let _: &[(); 0] = v.as_mut_array();
}
}
mod dox {
#[test]
fn test_readme_version() {
version_sync::assert_markdown_deps_updated!("README.md");
}
#[test]
fn test_html_root_url() {
version_sync::assert_html_root_url_updated!("lib.rs");
}
}
}