Skip to content

Commit a51eb70

Browse files
committed
Fix can_index_slice for arrays with no elements
1 parent 200d398 commit a51eb70

File tree

2 files changed

+50
-22
lines changed

2 files changed

+50
-22
lines changed

src/dimension.rs

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -61,33 +61,42 @@ pub fn dim_stride_overlap<D: Dimension>(dim: &D, strides: &D) -> bool {
6161
pub fn can_index_slice<A, D: Dimension>(data: &[A], dim: &D, strides: &D)
6262
-> Result<(), ShapeError>
6363
{
64-
if strides.slice().iter().cloned().all(stride_is_positive) {
65-
if dim.size_checked().is_none() {
64+
// check lengths of axes.
65+
let len = match dim.size_checked() {
66+
Some(l) => l,
67+
None => return Err(from_kind(ErrorKind::OutOfBounds)),
68+
};
69+
// check if strides are strictly positive (zero ok for len 0)
70+
for &s in strides.slice() {
71+
let s = s as Ixs;
72+
if s < 1 && (len != 0 || s < 0) {
73+
return Err(from_kind(ErrorKind::Unsupported));
74+
}
75+
}
76+
if len == 0 {
77+
return Ok(());
78+
}
79+
// check that the maximum index is in bounds
80+
let mut last_index = dim.clone();
81+
for mut index in last_index.slice_mut().iter_mut() {
82+
*index -= 1;
83+
}
84+
if let Some(offset) = stride_offset_checked_arithmetic(dim,
85+
strides,
86+
&last_index)
87+
{
88+
// offset is guaranteed to be positive so no issue converting
89+
// to usize here
90+
if (offset as usize) >= data.len() {
6691
return Err(from_kind(ErrorKind::OutOfBounds));
6792
}
68-
let mut last_index = dim.clone();
69-
for mut index in last_index.slice_mut().iter_mut() {
70-
*index -= 1;
71-
}
72-
if let Some(offset) = stride_offset_checked_arithmetic(dim,
73-
strides,
74-
&last_index)
75-
{
76-
// offset is guaranteed to be positive so no issue converting
77-
// to usize here
78-
if (offset as usize) >= data.len() {
79-
return Err(from_kind(ErrorKind::OutOfBounds));
80-
}
81-
if dim_stride_overlap(dim, strides) {
82-
return Err(from_kind(ErrorKind::Unsupported));
83-
}
84-
} else {
85-
return Err(from_kind(ErrorKind::OutOfBounds));
93+
if dim_stride_overlap(dim, strides) {
94+
return Err(from_kind(ErrorKind::Unsupported));
8695
}
87-
Ok(())
8896
} else {
89-
return Err(from_kind(ErrorKind::Unsupported));
97+
return Err(from_kind(ErrorKind::OutOfBounds));
9098
}
99+
Ok(())
91100
}
92101

93102
/// Return stride offset for this dimension and index.

tests/array.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,25 @@ fn from_vec_dim_stride_2d_6() {
511511
assert_matches!(OwnedArray::from_vec_dim_stride(d, s, a.to_vec()), Ok(_));
512512
}
513513

514+
#[test]
515+
fn from_vec_dim_stride_2d_7() {
516+
// empty arrays can have 0 strides
517+
let a: [f32; 0] = [];
518+
// [[]] shape=[4, 0], strides=[0, 1]
519+
let d = (4, 0);
520+
let s = (0, 1);
521+
assert_matches!(OwnedArray::from_vec_dim_stride(d, s, a.to_vec()), Ok(_));
522+
}
523+
524+
#[test]
525+
fn from_vec_dim_stride_2d_8() {
526+
// strides must be strictly positive (nonzero)
527+
let a = [1.];
528+
let d = (1, 1);
529+
let s = (0, 1);
530+
assert_matches!(OwnedArray::from_vec_dim_stride(d, s, a.to_vec()), Err(_));
531+
}
532+
514533
#[test]
515534
fn from_vec_dim_stride_2d_rejects() {
516535
let two = [1., 2.];

0 commit comments

Comments
 (0)