From 5a9ce394b43ac95252fc7e84bf88294fb5ade6d1 Mon Sep 17 00:00:00 2001 From: niluxv Date: Thu, 15 Jul 2021 09:48:13 +0200 Subject: [PATCH 1/5] Implement `Index` and `IndexMut` traits for `ArrayVec` --- src/arrayvec.rs | 48 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/src/arrayvec.rs b/src/arrayvec.rs index 6b4faf8..5564b53 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,42 @@ impl Extend for ArrayVec { } } +/// Perform the indexing (`container[index]`) operation. +/// +/// # Panics +/// Panics if index is out of bounds. +impl Index for ArrayVec +where + I: slice::SliceIndex<[T]>, +{ + type Output = >::Output; + + /// Performs the indexing (`container[index]`) operation. + /// + /// # Panics + /// Panics if index is out of bounds. + fn index(&self, index: I) -> &Self::Output { + self.deref().index(index) + } +} + +/// Perform the mutable indexing (`container[index]`) operation. +/// +/// # Panics +/// Panics if index is out of bounds. +impl IndexMut for ArrayVec +where + I: slice::SliceIndex<[T]>, +{ + /// Perform the mutable indexing (`container[index]`) operation. + /// + /// # Panics + /// Panics if index is out of bounds. + fn index_mut(&mut self, index: I) -> &mut Self::Output { + self.deref_mut().index_mut(index) + } +} + #[inline(never)] #[cold] fn extend_panic() { @@ -1072,11 +1108,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(); From 5b111f53fe0f651f5c725da6440d239d7266c373 Mon Sep 17 00:00:00 2001 From: niluxv Date: Sat, 24 Jul 2021 09:58:40 +0200 Subject: [PATCH 2/5] Add tests for `Index` and `IndexMut` trait implements --- tests/tests.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tests/tests.rs b/tests/tests.rs index 26d09ae..8691547 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() { From 3e2acd05435e7daa7900841a314725b2072f5071 Mon Sep 17 00:00:00 2001 From: niluxv Date: Sun, 15 Aug 2021 12:51:42 +0200 Subject: [PATCH 3/5] Change notation in Index[Mut] implementation --- src/arrayvec.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/arrayvec.rs b/src/arrayvec.rs index 5564b53..6df9057 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -1017,7 +1017,7 @@ where /// # Panics /// Panics if index is out of bounds. fn index(&self, index: I) -> &Self::Output { - self.deref().index(index) + &(**self)[index] } } @@ -1034,7 +1034,7 @@ where /// # Panics /// Panics if index is out of bounds. fn index_mut(&mut self, index: I) -> &mut Self::Output { - self.deref_mut().index_mut(index) + &mut (**self)[index] } } From 567a51d5fb02e2b1d5a33a066684809887f6cc27 Mon Sep 17 00:00:00 2001 From: niluxv Date: Sun, 15 Aug 2021 12:54:34 +0200 Subject: [PATCH 4/5] Make trait bound on Index[Mut] implementation more general --- src/arrayvec.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/arrayvec.rs b/src/arrayvec.rs index 6df9057..be79151 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -1008,9 +1008,9 @@ impl Extend for ArrayVec { /// Panics if index is out of bounds. impl Index for ArrayVec where - I: slice::SliceIndex<[T]>, + [T]: Index, { - type Output = >::Output; + type Output = <[T] as Index>::Output; /// Performs the indexing (`container[index]`) operation. /// @@ -1027,7 +1027,7 @@ where /// Panics if index is out of bounds. impl IndexMut for ArrayVec where - I: slice::SliceIndex<[T]>, + [T]: IndexMut, { /// Perform the mutable indexing (`container[index]`) operation. /// From a46074279365b277509a61fdf8410f79700d181b Mon Sep 17 00:00:00 2001 From: niluxv Date: Sun, 29 Aug 2021 20:21:40 +0200 Subject: [PATCH 5/5] Implement `Index` and `IndexMut` traits for `ArrayString` --- src/array_string.rs | 32 ++++++++++++++++++++++++++------ src/arrayvec.rs | 16 ---------------- tests/tests.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 22 deletions(-) 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 be79151..760b4d9 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -1002,37 +1002,21 @@ impl Extend for ArrayVec { } } -/// Perform the indexing (`container[index]`) operation. -/// -/// # Panics -/// Panics if index is out of bounds. impl Index for ArrayVec where [T]: Index, { type Output = <[T] as Index>::Output; - /// Performs the indexing (`container[index]`) operation. - /// - /// # Panics - /// Panics if index is out of bounds. fn index(&self, index: I) -> &Self::Output { &(**self)[index] } } -/// Perform the mutable indexing (`container[index]`) operation. -/// -/// # Panics -/// Panics if index is out of bounds. impl IndexMut for ArrayVec where [T]: IndexMut, { - /// Perform the mutable indexing (`container[index]`) operation. - /// - /// # Panics - /// Panics if index is out of bounds. fn index_mut(&mut self, index: I) -> &mut Self::Output { &mut (**self)[index] } diff --git a/tests/tests.rs b/tests/tests.rs index 8691547..90b9b81 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -644,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() {