diff --git a/src/lib.rs b/src/lib.rs index 11cdf13..1c3c15d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,11 +30,8 @@ extern crate core as std; use std::cmp; use std::iter; use std::mem; +use std::ops::{Bound, Deref, DerefMut, RangeBounds}; use std::ptr; -use std::ops::{ - Deref, - DerefMut, -}; use std::slice; // extra traits @@ -55,11 +52,9 @@ use serde::{Serialize, Deserialize, Serializer, Deserializer}; mod array; mod array_string; mod char; -mod range; mod errors; pub use crate::array::Array; -pub use crate::range::RangeArgument; use crate::array::Index; pub use crate::array_string::ArrayString; pub use crate::errors::CapacityError; @@ -572,7 +567,9 @@ impl ArrayVec { /// assert_eq!(&v[..], &[3]); /// assert_eq!(&u[..], &[1, 2]); /// ``` - pub fn drain(&mut self, range: R) -> Drain { + pub fn drain(&mut self, range: R) -> Drain + where R: RangeBounds + { // Memory safety // // When the Drain is first created, it shortens the length of @@ -584,8 +581,22 @@ impl ArrayVec { // the hole, and the vector length is restored to the new length. // let len = self.len(); - let start = range.start().unwrap_or(0); - let end = range.end().unwrap_or(len); + let start = match range.start_bound() { + Bound::Unbounded => 0, + Bound::Included(&i) => i, + Bound::Excluded(&i) => i.saturating_add(1), + }; + let end = match range.end_bound() { + Bound::Excluded(&j) => j, + Bound::Included(&j) => j.saturating_add(1), + Bound::Unbounded => len, + }; + self.drain_range(start, end) + } + + fn drain_range(&mut self, start: usize, end: usize) -> Drain + { + let len = self.len(); // bounds check happens here let range_slice: *const _ = &self[start..end]; diff --git a/src/range.rs b/src/range.rs deleted file mode 100644 index f90f5af..0000000 --- a/src/range.rs +++ /dev/null @@ -1,42 +0,0 @@ - -use std::ops::{ - RangeFull, - RangeFrom, - RangeTo, - Range, -}; - -/// `RangeArgument` is implemented by Rust's built-in range types, produced -/// by range syntax like `..`, `a..`, `..b` or `c..d`. -/// -/// Note: This is arrayvec's provisional trait, waiting for stable Rust to -/// provide an equivalent. -pub trait RangeArgument { - #[inline] - /// Start index (inclusive) - fn start(&self) -> Option { None } - #[inline] - /// End index (exclusive) - fn end(&self) -> Option { None } -} - - -impl RangeArgument for RangeFull {} - -impl RangeArgument for RangeFrom { - #[inline] - fn start(&self) -> Option { Some(self.start) } -} - -impl RangeArgument for RangeTo { - #[inline] - fn end(&self) -> Option { Some(self.end) } -} - -impl RangeArgument for Range { - #[inline] - fn start(&self) -> Option { Some(self.start) } - #[inline] - fn end(&self) -> Option { Some(self.end) } -} - diff --git a/tests/tests.rs b/tests/tests.rs index 1af779c..5ae1fc2 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -306,6 +306,29 @@ fn test_drain() { assert_eq!(&v[..], &[]); } +#[test] +fn test_drain_range_inclusive() { + let mut v = ArrayVec::from([0; 8]); + v.drain(0..=7); + assert_eq!(&v[..], &[]); + + v.extend(0..); + v.drain(1..=4); + assert_eq!(&v[..], &[0, 5, 6, 7]); + let u: ArrayVec<[_; 3]> = v.drain(1..=2).rev().collect(); + assert_eq!(&u[..], &[6, 5]); + assert_eq!(&v[..], &[0, 7]); + v.drain(..); + assert_eq!(&v[..], &[]); +} + +#[test] +#[should_panic] +fn test_drain_range_inclusive_oob() { + let mut v = ArrayVec::from([0; 0]); + v.drain(0..=0); +} + #[test] fn test_retain() { let mut v = ArrayVec::from([0; 8]);