Always check iterator size when allocating
This commit is contained in:
parent
afc03cc403
commit
3e07ad1b52
|
@ -36,12 +36,27 @@ pub trait Allocator<T, R: Dim, C: Dim = U1>: Any + Sized {
|
|||
unsafe fn assume_init(uninit: Self::BufferUninit) -> Self::Buffer;
|
||||
|
||||
/// Allocates a buffer initialized with the content of the given iterator.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if the iterator yields too few or too many
|
||||
/// elements.
|
||||
fn allocate_from_iterator<I: IntoIterator<Item = T>>(
|
||||
nrows: R,
|
||||
ncols: C,
|
||||
iter: I,
|
||||
) -> Self::Buffer;
|
||||
|
||||
/// Allocates a buffer from a `Vec<T>`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if the `Vec` contains too few or too many
|
||||
/// elements.
|
||||
fn allocate_from_vec(nrows: R, ncols: C, vec: Vec<T>) -> Self::Buffer {
|
||||
Self::allocate_from_iterator(nrows, ncols, vec)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Allocates a buffer initialized with the content of the given row-major order iterator.
|
||||
fn allocate_from_row_iterator<I: IntoIterator<Item = T>>(
|
||||
|
|
|
@ -331,7 +331,7 @@ where
|
|||
#[inline]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
pub fn from_vec_generic(nrows: R, ncols: C, data: Vec<T>) -> Self {
|
||||
Self::from_iterator_generic(nrows, ncols, data)
|
||||
Self::from_data(DefaultAllocator::allocate_from_vec(nrows, ncols, data))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -68,14 +68,16 @@ impl<T: Scalar, const R: usize, const C: usize> Allocator<T, Const<R>, Const<C>>
|
|||
|
||||
// Safety: conversion to a slice is OK because the Buffer is known to be contiguous.
|
||||
let res_slice = unsafe { res.as_mut_slice_unchecked() };
|
||||
for (res, e) in res_slice.iter_mut().zip(iter.into_iter()) {
|
||||
let mut it = iter.into_iter();
|
||||
for (res, e) in res_slice.iter_mut().zip(&mut it) {
|
||||
*res = MaybeUninit::new(e);
|
||||
count += 1;
|
||||
}
|
||||
|
||||
assert!(
|
||||
it.next().is_none() &&
|
||||
count == nrows.value() * ncols.value(),
|
||||
"Matrix init. from iterator: iterator not long enough."
|
||||
"Matrix init. from iterator: the iterator did not yield the correct number of elements."
|
||||
);
|
||||
|
||||
// Safety: the assertion above made sure that the iterator
|
||||
|
@ -121,13 +123,23 @@ impl<T: Scalar, C: Dim> Allocator<T, Dyn, C> for DefaultAllocator {
|
|||
ncols: C,
|
||||
iter: I,
|
||||
) -> Self::Buffer {
|
||||
let it = iter.into_iter();
|
||||
let res: Vec<T> = it.collect();
|
||||
assert!(res.len() == nrows.value() * ncols.value(),
|
||||
"Allocation from iterator error: the iterator did not yield the correct number of elements.");
|
||||
let size = nrows.value() * ncols.value();
|
||||
let mut it = iter.into_iter();
|
||||
let res: Vec<T> = (&mut it).take(size).collect();
|
||||
assert!(it.next().is_none() && res.len() == size,
|
||||
"Matrix init. from iterator: the iterator did not yield the correct number of elements.");
|
||||
|
||||
VecStorage::new(nrows, ncols, res)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn allocate_from_vec(nrows: Dyn, ncols: C, vec: Vec<T>) -> Self::Buffer {
|
||||
assert!(
|
||||
vec.len() == nrows.value() * ncols.value(),
|
||||
"Matrix init. from vec: the vec does not have the right size."
|
||||
);
|
||||
VecStorage::new(nrows, ncols, vec)
|
||||
}
|
||||
}
|
||||
|
||||
// Static - Dyn
|
||||
|
@ -167,13 +179,24 @@ impl<T: Scalar, R: DimName> Allocator<T, R, Dyn> for DefaultAllocator {
|
|||
ncols: Dyn,
|
||||
iter: I,
|
||||
) -> Self::Buffer {
|
||||
let it = iter.into_iter();
|
||||
let res: Vec<T> = it.collect();
|
||||
assert!(res.len() == nrows.value() * ncols.value(),
|
||||
"Allocation from iterator error: the iterator did not yield the correct number of elements.");
|
||||
let size = nrows.value() * ncols.value();
|
||||
let mut it = iter.into_iter();
|
||||
let res: Vec<T> = (&mut it).take(size).collect();
|
||||
assert!(it.next().is_none() && res.len() == size,
|
||||
"Matrix init. from iterator: the iterator did not yield the correct number of elements.");
|
||||
|
||||
VecStorage::new(nrows, ncols, res)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn allocate_from_vec(nrows: R, ncols: Dyn, vec: Vec<T>) -> Self::Buffer {
|
||||
assert_eq!(
|
||||
vec.len(),
|
||||
nrows.value() * ncols.value(),
|
||||
"Matrix init. from vec: the vec does not have the right size."
|
||||
);
|
||||
VecStorage::new(nrows, ncols, vec)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -333,3 +356,119 @@ impl<T: Scalar, RFrom: DimName, RTo: DimName> Reallocator<T, RFrom, Dyn, RTo, Dy
|
|||
VecStorage::new(rto, cto, new_buf)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
/// Tests for `DefaultAllocator` with constant dimensions.
|
||||
mod static_static {
|
||||
use crate::{allocator::Allocator, Const, DefaultAllocator};
|
||||
|
||||
#[test]
|
||||
#[should_panic(
|
||||
expected = "Matrix init. from iterator: the iterator did not yield the correct number of elements."
|
||||
)]
|
||||
fn allocate_from_iter_too_small() {
|
||||
let iter = &[1i32];
|
||||
let _ = DefaultAllocator::allocate_from_iterator(Const::<10>, Const::<5>, iter);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(
|
||||
expected = "Matrix init. from iterator: the iterator did not yield the correct number of elements."
|
||||
)]
|
||||
fn allocate_iter_too_big() {
|
||||
let iter = &[1u32, 2, 3, 4, 5, 6, 7];
|
||||
let _ = DefaultAllocator::allocate_from_iterator(Const::<2>, Const::<3>, iter);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(
|
||||
expected = "Matrix init. from iterator: the iterator did not yield the correct number of elements."
|
||||
)]
|
||||
fn allocate_from_vec_too_small() {
|
||||
let vec = vec![1u8];
|
||||
let _ = DefaultAllocator::allocate_from_vec(Const::<4>, Const::<2>, vec);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(
|
||||
expected = "Matrix init. from iterator: the iterator did not yield the correct number of elements."
|
||||
)]
|
||||
fn allocate_from_vec_too_big() {
|
||||
let vec = vec![1usize, 2, 3, 4, 5, 6];
|
||||
let _ = DefaultAllocator::allocate_from_vec(Const::<5>, Const::<1>, vec);
|
||||
}
|
||||
}
|
||||
|
||||
mod dyn_static {
|
||||
use crate::{allocator::Allocator, Const, DefaultAllocator, Dyn};
|
||||
|
||||
#[test]
|
||||
#[should_panic(
|
||||
expected = "Matrix init. from iterator: the iterator did not yield the correct number of elements."
|
||||
)]
|
||||
fn allocate_from_iter_too_small() {
|
||||
let iter = &[1i32];
|
||||
let _ = DefaultAllocator::allocate_from_iterator(Dyn(4), Const::<5>, iter);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(
|
||||
expected = "Matrix init. from iterator: the iterator did not yield the correct number of elements."
|
||||
)]
|
||||
fn allocate_iter_too_big() {
|
||||
let iter = &[1u32, 2, 3, 4];
|
||||
let _ = DefaultAllocator::allocate_from_iterator(Dyn(1), Const::<3>, iter);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Matrix init. from vec: the vec does not have the right size.")]
|
||||
fn allocate_from_vec_too_small() {
|
||||
let vec = vec![1u8];
|
||||
let _ = DefaultAllocator::allocate_from_vec(Dyn(4), Const::<2>, vec);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Matrix init. from vec: the vec does not have the right size.")]
|
||||
fn allocate_from_vec_too_big() {
|
||||
let vec = vec![1usize, 2, 3, 4, 5, 6];
|
||||
let _ = DefaultAllocator::allocate_from_vec(Dyn(5), Const::<1>, vec);
|
||||
}
|
||||
}
|
||||
|
||||
mod static_dyn {
|
||||
use crate::{allocator::Allocator, Const, DefaultAllocator, Dyn};
|
||||
|
||||
#[test]
|
||||
#[should_panic(
|
||||
expected = "Matrix init. from iterator: the iterator did not yield the correct number of elements."
|
||||
)]
|
||||
fn allocate_from_iter_too_small() {
|
||||
let iter = &[1i32];
|
||||
let _ = DefaultAllocator::allocate_from_iterator(Const::<5>, Dyn(4), iter);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(
|
||||
expected = "Matrix init. from iterator: the iterator did not yield the correct number of elements."
|
||||
)]
|
||||
fn allocate_iter_too_big() {
|
||||
let iter = &[1u32, 2, 3, 4];
|
||||
let _ = DefaultAllocator::allocate_from_iterator(Const::<3>, Dyn(1), iter);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Matrix init. from vec: the vec does not have the right size.")]
|
||||
fn allocate_from_vec_too_small() {
|
||||
let vec = vec![1u8];
|
||||
let _ = DefaultAllocator::allocate_from_vec(Const::<2>, Dyn(4), vec);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Matrix init. from vec: the vec does not have the right size.")]
|
||||
fn allocate_from_vec_too_big() {
|
||||
let vec = vec![1usize, 2, 3, 4, 5, 6];
|
||||
let _ = DefaultAllocator::allocate_from_vec(Const::<1>, Dyn(5), vec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -208,19 +208,19 @@ fn new_from_slice() {
|
|||
5.0, 6.0, 7.0, 8.0,
|
||||
9.0, 10.0, 11.0, 12.0 ];
|
||||
|
||||
let expected2 = Matrix2::from_column_slice(&data);
|
||||
let expected3 = Matrix3::from_column_slice(&data);
|
||||
let expected2x3 = Matrix2x3::from_column_slice(&data);
|
||||
let expected3x2 = Matrix3x2::from_column_slice(&data);
|
||||
let expected2 = Matrix2::from_column_slice(&data[0..4]);
|
||||
let expected3 = Matrix3::from_column_slice(&data[0..9]);
|
||||
let expected2x3 = Matrix2x3::from_column_slice(&data[0..6]);
|
||||
let expected3x2 = Matrix3x2::from_column_slice(&data[0..6]);
|
||||
|
||||
{
|
||||
let m2 = MatrixView2::from_slice(&data);
|
||||
let m3 = MatrixView3::from_slice(&data);
|
||||
let m2x3 = MatrixView2x3::from_slice(&data);
|
||||
let m3x2 = MatrixView3x2::from_slice(&data);
|
||||
let m2xX = MatrixView2xX::from_slice(&data, 3);
|
||||
let mXx3 = MatrixViewXx3::from_slice(&data, 2);
|
||||
let mXxX = DMatrixView::from_slice(&data, 2, 3);
|
||||
let m2 = MatrixView2::from_slice(&data[0..4]);
|
||||
let m3 = MatrixView3::from_slice(&data[0..9]);
|
||||
let m2x3 = MatrixView2x3::from_slice(&data[0..6]);
|
||||
let m3x2 = MatrixView3x2::from_slice(&data[0..6]);
|
||||
let m2xX = MatrixView2xX::from_slice(&data[0..6], 3);
|
||||
let mXx3 = MatrixViewXx3::from_slice(&data[0..6], 2);
|
||||
let mXxX = DMatrixView::from_slice(&data[0..6], 2, 3);
|
||||
|
||||
assert!(m2.eq(&expected2));
|
||||
assert!(m3.eq(&expected3));
|
||||
|
|
Loading…
Reference in New Issue