From 5fb7658ae9fc9382d8eed71ba58e52227c0976c7 Mon Sep 17 00:00:00 2001
From: Shawn Tabrizi <shawntabrizi@gmail.com>
Date: Tue, 4 May 2021 05:17:52 -0400
Subject: [PATCH] Improve `BoundedVec` API (#8707)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* improve bounded vec api

* Update frame/support/src/storage/bounded_vec.rs

Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com>

* Update frame/support/src/storage/bounded_vec.rs

* Update frame/support/src/storage/bounded_vec.rs

Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com>
Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
---
 .../frame/support/src/storage/bounded_vec.rs  | 48 +++++++++++++++++--
 1 file changed, 44 insertions(+), 4 deletions(-)

diff --git a/substrate/frame/support/src/storage/bounded_vec.rs b/substrate/frame/support/src/storage/bounded_vec.rs
index 9fcfe403529..5b253f76333 100644
--- a/substrate/frame/support/src/storage/bounded_vec.rs
+++ b/substrate/frame/support/src/storage/bounded_vec.rs
@@ -21,6 +21,7 @@
 use sp_std::prelude::*;
 use sp_std::{convert::TryFrom, marker::PhantomData};
 use codec::{FullCodec, Encode, EncodeLike, Decode};
+use core::{ops::{Index, IndexMut}, slice::SliceIndex};
 use crate::{
 	traits::Get,
 	storage::{generator, StorageDecodeLength, StorageValue, StorageMap, StorageDoubleMap},
@@ -179,6 +180,18 @@ impl<T: BoundedVecValue, S: Get<u32>> AsRef<Vec<T>> for BoundedVec<T, S> {
 	}
 }
 
+impl<T: BoundedVecValue, S: Get<u32>> AsRef<[T]> for BoundedVec<T, S> {
+	fn as_ref(&self) -> &[T] {
+		&self.0
+	}
+}
+
+impl<T: BoundedVecValue, S: Get<u32>> AsMut<[T]> for BoundedVec<T, S> {
+	fn as_mut(&mut self) -> &mut [T] {
+		&mut self.0
+	}
+}
+
 // will allow for immutable all operations of `Vec<T>` on `BoundedVec<T>`.
 impl<T: BoundedVecValue, S: Get<u32>> sp_std::ops::Deref for BoundedVec<T, S> {
 	type Target = Vec<T>;
@@ -189,10 +202,19 @@ impl<T: BoundedVecValue, S: Get<u32>> sp_std::ops::Deref for BoundedVec<T, S> {
 }
 
 // Allows for indexing similar to a normal `Vec`. Can panic if out of bound.
-impl<T: BoundedVecValue, S: Get<u32>> sp_std::ops::Index<usize> for BoundedVec<T, S> {
-	type Output = T;
-	fn index(&self, index: usize) -> &Self::Output {
-		self.get(index).expect("index out of bound")
+impl<T: BoundedVecValue, S: Get<u32>, I: SliceIndex<[T]>> Index<I> for BoundedVec<T, S> {
+	type Output = I::Output;
+
+	#[inline]
+	fn index(&self, index: I) -> &Self::Output {
+		self.0.index(index)
+	}
+}
+
+impl<T: BoundedVecValue, S: Get<u32>, I: SliceIndex<[T]>> IndexMut<I> for BoundedVec<T, S> {
+	#[inline]
+	fn index_mut(&mut self, index: I) -> &mut Self::Output {
+		self.0.index_mut(index)
 	}
 }
 
@@ -212,6 +234,12 @@ impl<T: BoundedVecValue, S: Get<u32>> codec::DecodeLength for BoundedVec<T, S> {
 	}
 }
 
+impl<T: BoundedVecValue + PartialEq, S: Get<u32>> PartialEq<Vec<T>> for BoundedVec<T, S> {
+	fn eq(&self, other: &Vec<T>) -> bool {
+		&self.0 == other
+	}
+}
+
 impl<T: BoundedVecValue, S: Get<u32>> StorageDecodeLength for BoundedVec<T, S> {}
 
 /// Storage value that is *maybe* capable of [`StorageAppend`](crate::storage::StorageAppend).
@@ -467,4 +495,16 @@ pub mod test {
 		assert_eq!(bounded.len(), 7);
 		assert!(bounded.try_mutate(|v| v.push(8)).is_none());
 	}
+
+	#[test]
+	fn slice_indexing_works() {
+		let bounded: BoundedVec<u32, Seven> = vec![1, 2, 3, 4, 5, 6].try_into().unwrap();
+		assert_eq!(&bounded[0..=2], &[1, 2, 3]);
+	}
+
+	#[test]
+	fn vec_eq_works() {
+		let bounded: BoundedVec<u32, Seven> = vec![1, 2, 3, 4, 5, 6].try_into().unwrap();
+		assert_eq!(bounded, vec![1, 2, 3, 4, 5, 6]);
+	}
 }
-- 
GitLab