#![doc(html_root_url = "https://docs.rs/slice-of-array/0.2.0")]
#[cfg(test)]
#[macro_use]
extern crate version_sync;
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;
}
macro_rules! impl_approved_array {
($($n:tt)+) => {$(
unsafe impl<T> IsSliceomorphic for [T; $n] {
type Element = T;
const LEN: usize = $n;
}
)+};
}
impl_approved_array!{
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
}
fn validate_some_assumptions<V: IsSliceomorphic>() {
use ::std::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] {
unsafe {
validate_some_assumptions::<V>();
::std::slice::from_raw_parts(
self.as_ptr() as *const _,
self.len() * V::LEN,
)
}
}
fn flat_mut(&mut self) -> &mut [V::Element] {
unsafe {
validate_some_assumptions::<V>();
::std::slice::from_raw_parts_mut(
self.as_mut_ptr() as *mut _,
self.len() * V::LEN,
)
}
}
}
impl<T> SliceNestExt<T> for [T] {
fn nest<V: IsSliceomorphic<Element=T>>(&self) -> &[V] {
validate_some_assumptions::<V>();
assert_eq!(0, self.len() % V::LEN,
"cannot view slice of length {} as &[[_; {}]]",
self.len(), V::LEN);
unsafe { ::std::slice::from_raw_parts(
self.as_ptr() as *const _,
self.len() / V::LEN,
)}
}
fn nest_mut<V: IsSliceomorphic<Element=T>>(&mut self) -> &mut [V] {
validate_some_assumptions::<V>();
assert_eq!(0, self.len() % V::LEN,
"cannot view slice of length {} as &mut [[_; {}]]",
self.len(), V::LEN);
unsafe { ::std::slice::from_raw_parts_mut(
self.as_ptr() as *mut _,
self.len() / V::LEN,
)}
}
}
impl<T> SliceArrayExt<T> for [T] {
fn as_array<V: IsSliceomorphic<Element=T>>(&self) -> &V {
assert_eq!(self.len(), V::LEN,
"cannot view slice of length {} as &[_; {}]",
self.len(), V::LEN);
&self.nest()[0]
}
fn as_mut_array<V: IsSliceomorphic<Element=T>>(&mut self) -> &mut V {
assert_eq!(self.len(), V::LEN,
"cannot view slice of length {} as &mut [_; {}]",
self.len(), V::LEN);
&mut self.nest_mut()[0]
}
}
#[cfg(test)]
mod tests {
pub use super::prelude::*;
#[test]
fn inference_lattice() {
let mut v = vec![(); 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(); }
{ let _: Vec<[(); 3]> = v.nest().to_vec(); }
}
mod failures {
use super::super::*;
#[test]
#[should_panic(expected = "cannot view slice of length 8")]
fn fail_nest_not_multiple() {
let v = vec![(); 8];
let _: &[[(); 3]] = v.nest();
}
#[test]
#[should_panic(expected = "cannot view slice of length 8")]
fn nest_mut_not_multiple() {
let mut v = vec![(); 8];
let _: &mut [[(); 3]] = v.nest_mut();
}
#[test]
#[should_panic(expected = "cannot view slice of length 1")]
fn as_array_too_small() {
let v = vec![(); 1];
let _: &[(); 3] = v.as_array();
}
#[test]
#[should_panic(expected = "cannot view slice of length 6")]
fn as_array_too_large() {
let v = vec![(); 6];
let _: &[(); 3] = v.as_array();
}
#[test]
#[should_panic(expected = "cannot view slice of length 1")]
fn as_mut_array_too_small() {
let mut v = vec![(); 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 mut v = vec![(); 6];
let _: &mut [(); 3] = v.as_mut_array();
}
}
mod dox {
#[test]
fn test_readme_version() {
assert_markdown_deps_updated!("README.md");
}
#[test]
fn test_html_root_url() {
assert_html_root_url_updated!("lib.rs");
}
}
}