Skip to content

Commit

Permalink
Relax bounds checks on Focus::narrow and split_at
Browse files Browse the repository at this point in the history
  • Loading branch information
goffrie committed Jan 17, 2025
1 parent 8668338 commit 425965c
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/vector/focus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ where
R: RangeBounds<usize>,
{
let r = to_range(&range, self.len());
if r.start >= r.end || r.start >= self.len() {
if r.start > r.end || r.end > self.len() {
panic!("vector::Focus::narrow: range out of bounds");
}
match self {
Expand Down Expand Up @@ -232,7 +232,7 @@ where
/// [slice::split_at]: https://doc.rust-lang.org/std/primitive.slice.html#method.split_at
/// [Vector::split_at]: enum.Vector.html#method.split_at
pub fn split_at(self, index: usize) -> (Self, Self) {
if index >= self.len() {
if index > self.len() {
panic!("vector::Focus::split_at: index out of bounds");
}
match self {
Expand Down
57 changes: 57 additions & 0 deletions src/vector/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2412,6 +2412,63 @@ mod test {
assert_eq!(0, vec[0]);
}

#[test]
fn test_vector_focus_split_at() {
for (data, split_points) in [
(0..0, vec![0]),
(0..3, vec![0, 1, 2, 3]),
(0..128, vec![0, 1, 64, 127, 128]),
#[cfg(not(miri))]
(0..100_000, vec![0, 1, 50_000, 99_999, 100_000]),
] {
let imbl_vec = Vector::from_iter(data.clone());
let vec = Vec::from_iter(data);
let focus = imbl_vec.focus();
for split_point in split_points {
let (left, right) = focus.clone().split_at(split_point);
let (expected_left, expected_right) = vec.split_at(split_point);
assert_eq!(
left.clone().into_iter().copied().collect::<Vec<_>>(),
expected_left
);
assert_eq!(
right.clone().into_iter().copied().collect::<Vec<_>>(),
expected_right
);
}
}
}

#[test]
#[should_panic(expected = "range out of bounds")]
fn test_vector_focus_narrow_out_of_range() {
let vec = Vector::from_iter(0..100);
_ = vec.focus().narrow(..1000);
}

#[test]
fn test_vector_focus_narrow() {
macro_rules! testcase {
($data:expr, $range:expr) => ({
let imbl_vector = Vector::from_iter($data);
let vec = Vec::from_iter($data);
let focus = imbl_vector.focus();
assert_eq!(focus.narrow($range).into_iter().copied().collect::<Vec<_>>(), vec[$range]);
})
}
// exhaustively test small cases
for len in 0..=3 {
testcase!(0..len, ..);
for start in 0..=len {
testcase!(0..len, start..);
testcase!(0..len, ..start);
for end in start..=len {
testcase!(0..len, start..end);
}
}
}
}

#[cfg_attr(miri, ignore)]
#[test]
fn large_vector_focus() {
Expand Down

0 comments on commit 425965c

Please sign in to comment.