#[macro_export]
macro_rules! try_vec_to_array {
($vec:ident, $t:ty, $size:expr) => {
{
if $vec.len() == $size {
let mut arr: [std::mem::MaybeUninit<$t>; $size] = unsafe {
std::mem::MaybeUninit::uninit().assume_init()
};
for (i, item) in $vec.into_iter().enumerate() {
arr[i] = std::mem::MaybeUninit::new(item);
}
Ok(unsafe { std::mem::transmute::<_, [$t; $size]>(arr) })
} else {
Err($crate::VecToArrayError::SizeMismatch { expected: $size, found: $vec.len() })
}
}
}
}
#[macro_export]
macro_rules! vec_to_array {
($vec:ident, $t:ty, $size:expr) => {
{
if $vec.len() != $size {
panic!("{}", $crate::VecToArrayError::SizeMismatch {
expected: $size,
found: $vec.len()
});
}
let mut arr: [std::mem::MaybeUninit<$t>; $size] = unsafe {
std::mem::MaybeUninit::uninit().assume_init()
};
for (i, item) in $vec.into_iter().enumerate() {
arr[i] = std::mem::MaybeUninit::new(item);
}
unsafe { std::mem::transmute::<_, [$t; $size]>(arr) }
}
}
}
#[derive(Debug)]
pub enum VecToArrayError {
SizeMismatch { expected: usize, found: usize },
}
impl std::fmt::Display for VecToArrayError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
VecToArrayError::SizeMismatch { expected, found } => write!(f, "Expected vector of size {}, but found size {}", expected, found),
}
}
}
impl std::error::Error for VecToArrayError {}
#[cfg(test)]
mod tests {
use crate::VecToArrayError;
#[test]
fn basic_test() {
let vec: Vec<i64> = vec![1, 2, 3];
let array: [i64; 3] = vec_to_array!(vec, i64, 3);
assert_eq!(array, [1, 2, 3]);
let vec: Vec<i32> = vec![1, 2, 3];
let array: Result<[i32; 3], VecToArrayError> = try_vec_to_array!(vec, i32, 3);
assert_eq!(array.unwrap(), [1, 2, 3]);
let v: Vec<i32> = vec![0; 768];
let _arr: [i32; 768] = vec_to_array!(v, i32, 768);
let v: Vec<i32> = Vec::with_capacity(768);
let arr = try_vec_to_array!(v, i32, 768);
match arr {
Err(VecToArrayError::SizeMismatch { expected: 768, found: 0 }) => (),
_ => panic!()
}
let v: Vec<i32> = vec![0; 768];
let arr: Result<[i32; 768], VecToArrayError> = try_vec_to_array!(v, i32, 768);
assert!(arr.is_ok());
}
#[test]
fn more_complex_test() {
let mut x: Vec<Vec<String>> = Vec::new();
x.push(vec![String::from("12"), String::from("3")]);
let exp = x.clone();
let y: [Vec<String>; 1] = vec_to_array!(x, Vec<String>, 1);
let act = y.to_vec();
assert_eq!(act, exp);
}
#[test]
fn test_will_not_panic() {
let v: Vec<i32> = vec![0; 768];
let _arr: Result<[i32; 769], VecToArrayError> = try_vec_to_array!(v, i32, 769);
let v: Vec<i32> = vec![0; 768];
let _arr: Result<[i32; 767], VecToArrayError> = try_vec_to_array!(v, i32, 767);
}
#[test]
#[should_panic]
fn test_panics1() {
let v: Vec<i32> = vec![0; 768];
let _arr: [i32; 767] = vec_to_array!(v, i32, 767);
}
#[test]
#[should_panic]
fn test_panics2() {
let v: Vec<i32> = vec![0; 768];
let _arr: [i32; 769] = vec_to_array!(v, i32, 769);
}
#[test]
#[should_panic]
fn test_panics3() {
let v: Vec<i32> = Vec::with_capacity(768);
let _arr: [i32; 768] = vec_to_array!(v, i32, 768);
}
}