diff --git a/src/array_string.rs b/src/array_string.rs index a044cb5..00ca5ed 100644 --- a/src/array_string.rs +++ b/src/array_string.rs @@ -4,7 +4,7 @@ use std::convert::TryFrom; use std::fmt; use std::hash::{Hash, Hasher}; use std::mem::MaybeUninit; -use std::ops::{Deref, DerefMut}; +use std::ops::{Deref, DerefMut, Index, IndexMut}; use std::ptr; use std::slice; use std::str; @@ -261,7 +261,7 @@ impl ArrayString /// /// ``` /// use arrayvec::ArrayString; - /// + /// /// let mut s = ArrayString::<3>::from("foo").unwrap(); /// /// assert_eq!(s.pop(), Some('o')); @@ -301,7 +301,7 @@ impl ArrayString pub fn truncate(&mut self, new_len: usize) { if new_len <= self.len() { assert!(self.is_char_boundary(new_len)); - unsafe { + unsafe { // In libstd truncate is called on the underlying vector, // which in turns drops each element. // As we know we don't have to worry about Drop, @@ -321,7 +321,7 @@ impl ArrayString /// /// ``` /// use arrayvec::ArrayString; - /// + /// /// let mut s = ArrayString::<3>::from("foo").unwrap(); /// /// assert_eq!(s.remove(0), 'f'); @@ -429,7 +429,7 @@ impl PartialEq> for str } } -impl Eq for ArrayString +impl Eq for ArrayString { } impl Hash for ArrayString @@ -449,6 +449,26 @@ impl AsRef for ArrayString fn as_ref(&self) -> &str { self } } +impl Index for ArrayString +where + str: Index, +{ + type Output = >::Output; + + fn index(&self, index: I) -> &Self::Output { + &(**self)[index] + } +} + +impl IndexMut for ArrayString +where + str: IndexMut, +{ + fn index_mut(&mut self, index: I) -> &mut Self::Output { + &mut (**self)[index] + } +} + impl fmt::Debug for ArrayString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } @@ -545,7 +565,7 @@ impl Serialize for ArrayString #[cfg(feature="serde")] /// Requires crate feature `"serde"` -impl<'de, const CAP: usize> Deserialize<'de> for ArrayString +impl<'de, const CAP: usize> Deserialize<'de> for ArrayString { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> diff --git a/src/arrayvec.rs b/src/arrayvec.rs index 6b4faf8..760b4d9 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -2,7 +2,7 @@ use std::cmp; use std::iter; use std::mem; -use std::ops::{Bound, Deref, DerefMut, RangeBounds}; +use std::ops::{Bound, Deref, DerefMut, Index, IndexMut, RangeBounds}; use std::ptr; use std::slice; @@ -373,7 +373,7 @@ impl ArrayVec { /// Remove the element at `index` and swap the last element into its place. /// - /// This is a checked version of `.swap_remove`. + /// This is a checked version of `.swap_remove`. /// This operation is O(1). /// /// Return `Some(` *element* `)` if the index is in bounds, else `None`. @@ -989,11 +989,11 @@ impl Drop for ScopeExitGuard /// Extend the `ArrayVec` with an iterator. -/// +/// /// ***Panics*** if extending the vector exceeds its capacity. impl Extend for ArrayVec { /// Extend the `ArrayVec` with an iterator. - /// + /// /// ***Panics*** if extending the vector exceeds its capacity. fn extend>(&mut self, iter: I) { unsafe { @@ -1002,6 +1002,26 @@ impl Extend for ArrayVec { } } +impl Index for ArrayVec +where + [T]: Index, +{ + type Output = <[T] as Index>::Output; + + fn index(&self, index: I) -> &Self::Output { + &(**self)[index] + } +} + +impl IndexMut for ArrayVec +where + [T]: IndexMut, +{ + fn index_mut(&mut self, index: I) -> &mut Self::Output { + &mut (**self)[index] + } +} + #[inline(never)] #[cold] fn extend_panic() { @@ -1072,11 +1092,11 @@ unsafe fn raw_ptr_add(ptr: *mut T, offset: usize) -> *mut T { } /// Create an `ArrayVec` from an iterator. -/// +/// /// ***Panics*** if the number of elements in the iterator exceeds the arrayvec's capacity. impl iter::FromIterator for ArrayVec { /// Create an `ArrayVec` from an iterator. - /// + /// /// ***Panics*** if the number of elements in the iterator exceeds the arrayvec's capacity. fn from_iter>(iter: I) -> Self { let mut array = ArrayVec::new(); diff --git a/tests/tests.rs b/tests/tests.rs index 26d09ae..90b9b81 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -520,6 +520,46 @@ fn array_clone_from() { assert_eq!(&t, &reference[..]); } +#[test] +fn array_index_usize() { + let v = ArrayVec::from([1, 2, 3]); + assert_eq!(v[1], 2); +} + +#[should_panic(expected="index out of bounds: the len is 3 but the index is 3")] +#[test] +fn array_index_usize_out_of_bounds() { + let v = ArrayVec::from([1, 2, 3]); + let _ = v[3]; // out of bounds +} + +#[test] +fn array_index_range() { + let v = ArrayVec::from([1, 2, 3]); + assert_eq!(&v[1..3], [2, 3].as_ref()); +} + +#[should_panic(expected="range end index 4 out of range for slice of length 3")] +#[test] +fn array_index_range_out_of_bounds() { + let v = ArrayVec::from([1, 2, 3]); + let _ = v[1..4]; // out of bounds +} + +#[test] +fn array_indexmut_usize() { + let mut v = ArrayVec::from([1, 2, 3]); + v[1] = 0; + assert_eq!(v, ArrayVec::from([1, 0, 3])); +} + +#[should_panic(expected="index out of bounds: the len is 3 but the index is 3")] +#[test] +fn array_indexmut_usize_out_of_bounds() { + let mut v = ArrayVec::from([1, 2, 3]); + v[3] = 0; // out of bounds +} + #[cfg(feature="std")] #[test] fn test_string() { @@ -604,6 +644,46 @@ fn test_string_push() { assert!(s.try_push('x').is_err()); } +#[test] +fn string_index() { + let v = ArrayString::<9>::from("abcαβγ").unwrap(); + assert_eq!(&v[1..5], "bcα"); +} + +#[should_panic(expected="byte index 4 is out of bounds of `abc`")] +#[test] +fn string_index_out_of_bounds() { + let v = ArrayString::<3>::from("abc").unwrap(); + let _ = v[1..4]; // out of bounds +} + +#[should_panic(expected="byte index 1 is not a char boundary; it is inside 'α' (bytes 0..2) of `αβγabc`")] +#[test] +fn string_index_char_boundary_error() { + let v = ArrayString::<9>::from("αβγabc").unwrap(); + let _ = v[1..4]; // not at char boundary +} + +#[test] +fn string_indexmut() { + let mut v = ArrayString::<9>::from("αβγabc").unwrap(); + v[4..7].make_ascii_uppercase(); + assert_eq!(&*v, "αβγAbc"); +} + +#[should_panic(expected="byte index 4 is out of bounds of `abc`")] +#[test] +fn string_indexmut_out_of_bounds() { + let mut v = ArrayString::<3>::from("abc").unwrap(); + v[2..4].make_ascii_uppercase(); // out of bounds +} + +#[should_panic(expected="byte index 1 is not a char boundary; it is inside 'α' (bytes 0..2) of `αβγabc`")] +#[test] +fn string_indexmut_char_boundary_error() { + let mut v = ArrayString::<9>::from("αβγabc").unwrap(); + v[1..4].make_ascii_uppercase(); // not at char boundary +} #[test] fn test_insert_at_length() {