From 6a81ce90eff15beaefa2d60e793b99496b88cad0 Mon Sep 17 00:00:00 2001 From: Keith Yeung Date: Mon, 13 Jun 2022 15:05:12 +0100 Subject: [PATCH 1/4] Implement PartialOrd and Ord on BoundedSlice and WeakBoundedVec --- primitives/runtime/src/bounded/bounded_vec.rs | 16 ++++++++++++++-- .../runtime/src/bounded/weak_bounded_vec.rs | 12 ++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/primitives/runtime/src/bounded/bounded_vec.rs b/primitives/runtime/src/bounded/bounded_vec.rs index 4493d9f8b0198..b9cdef9de8da4 100644 --- a/primitives/runtime/src/bounded/bounded_vec.rs +++ b/primitives/runtime/src/bounded/bounded_vec.rs @@ -117,13 +117,13 @@ impl<'a, T: Encode + Decode, S: Get> EncodeLike> } impl<'a, T: Encode + Decode, S: Get> EncodeLike> for BoundedSlice<'a, T, S> {} -impl> PartialOrd for BoundedVec { +impl<'a, T: PartialOrd, Bound: Get> PartialOrd for BoundedSlice<'a, T, Bound> { fn partial_cmp(&self, other: &Self) -> Option { self.0.partial_cmp(&other.0) } } -impl> Ord for BoundedVec { +impl<'a, T: Ord, Bound: Get> Ord for BoundedSlice<'a, T, Bound> { fn cmp(&self, other: &Self) -> sp_std::cmp::Ordering { self.0.cmp(&other.0) } @@ -653,6 +653,18 @@ impl> PartialEq> for BoundedVec { impl> Eq for BoundedVec where T: Eq {} +impl> PartialOrd for BoundedVec { + fn partial_cmp(&self, other: &Self) -> Option { + self.0.partial_cmp(&other.0) + } +} + +impl> Ord for BoundedVec { + fn cmp(&self, other: &Self) -> sp_std::cmp::Ordering { + self.0.cmp(&other.0) + } +} + impl MaxEncodedLen for BoundedVec where T: MaxEncodedLen, diff --git a/primitives/runtime/src/bounded/weak_bounded_vec.rs b/primitives/runtime/src/bounded/weak_bounded_vec.rs index 9b88ad27e4287..0c0857c12be9a 100644 --- a/primitives/runtime/src/bounded/weak_bounded_vec.rs +++ b/primitives/runtime/src/bounded/weak_bounded_vec.rs @@ -303,6 +303,18 @@ impl> PartialEq> for WeakBoundedVec { impl Eq for WeakBoundedVec where T: Eq {} +impl> PartialOrd for WeakBoundedVec { + fn partial_cmp(&self, other: &Self) -> Option { + self.0.partial_cmp(&other.0) + } +} + +impl> Ord for WeakBoundedVec { + fn cmp(&self, other: &Self) -> sp_std::cmp::Ordering { + self.0.cmp(&other.0) + } +} + impl MaxEncodedLen for WeakBoundedVec where T: MaxEncodedLen, From 77772d0918d089dc12c3c5f79066e4dffe93bf1b Mon Sep 17 00:00:00 2001 From: Keith Yeung Date: Mon, 13 Jun 2022 16:11:55 +0100 Subject: [PATCH 2/4] More implementations of PartialEq and PartialOrd --- .../runtime/src/bounded/bounded_btree_map.rs | 8 +- .../runtime/src/bounded/bounded_btree_set.rs | 8 +- primitives/runtime/src/bounded/bounded_vec.rs | 131 +++++++++++++++++- .../runtime/src/bounded/weak_bounded_vec.rs | 70 ++++++++-- 4 files changed, 197 insertions(+), 20 deletions(-) diff --git a/primitives/runtime/src/bounded/bounded_btree_map.rs b/primitives/runtime/src/bounded/bounded_btree_map.rs index f4fd4275beb2a..b9abf77f175c6 100644 --- a/primitives/runtime/src/bounded/bounded_btree_map.rs +++ b/primitives/runtime/src/bounded/bounded_btree_map.rs @@ -66,6 +66,11 @@ where K: Ord, S: Get, { + /// Create `Self` from `t` without any checks. + fn unchecked_from(t: BTreeMap) -> Self { + Self(t, Default::default()) + } + /// Exactly the same semantics as `BTreeMap::retain`. /// /// The is a safe `&mut self` borrow because `retain` can only ever decrease the length of the @@ -344,8 +349,7 @@ where if self.len() > Bound::get() as usize { Err("iterator length too big") } else { - Ok(BoundedBTreeMap::::try_from(self.collect::>()) - .expect("length checked above; qed")) + Ok(BoundedBTreeMap::::unchecked_from(self.collect::>())) } } } diff --git a/primitives/runtime/src/bounded/bounded_btree_set.rs b/primitives/runtime/src/bounded/bounded_btree_set.rs index 40b95165da1bd..0f8cc769e47e3 100644 --- a/primitives/runtime/src/bounded/bounded_btree_set.rs +++ b/primitives/runtime/src/bounded/bounded_btree_set.rs @@ -65,6 +65,11 @@ where T: Ord, S: Get, { + /// Create `Self` from `t` without any checks. + fn unchecked_from(t: BTreeSet) -> Self { + Self(t, Default::default()) + } + /// Create a new `BoundedBTreeSet`. /// /// Does not allocate. @@ -309,8 +314,7 @@ where if self.len() > Bound::get() as usize { Err("iterator length too big") } else { - Ok(BoundedBTreeSet::::try_from(self.collect::>()) - .expect("length is checked above; qed")) + Ok(BoundedBTreeSet::::unchecked_from(self.collect::>())) } } } diff --git a/primitives/runtime/src/bounded/bounded_vec.rs b/primitives/runtime/src/bounded/bounded_vec.rs index b9cdef9de8da4..9cdcce9711541 100644 --- a/primitives/runtime/src/bounded/bounded_vec.rs +++ b/primitives/runtime/src/bounded/bounded_vec.rs @@ -43,7 +43,7 @@ use sp_std::{marker::PhantomData, prelude::*}; #[derive(Encode, scale_info::TypeInfo)] #[scale_info(skip_type_params(S))] pub struct BoundedVec( - Vec, + pub(super) Vec, #[cfg_attr(feature = "std", serde(skip_serializing))] PhantomData, ); @@ -106,7 +106,7 @@ where /// Similar to a `BoundedVec`, but not owned and cannot be decoded. #[derive(Encode, scale_info::TypeInfo)] #[scale_info(skip_type_params(S))] -pub struct BoundedSlice<'a, T, S>(&'a [T], PhantomData); +pub struct BoundedSlice<'a, T, S>(pub(super) &'a [T], PhantomData); // `BoundedSlice`s encode to something which will always decode into a `BoundedVec`, // `WeakBoundedVec`, or a `Vec`. @@ -117,12 +117,80 @@ impl<'a, T: Encode + Decode, S: Get> EncodeLike> } impl<'a, T: Encode + Decode, S: Get> EncodeLike> for BoundedSlice<'a, T, S> {} -impl<'a, T: PartialOrd, Bound: Get> PartialOrd for BoundedSlice<'a, T, Bound> { - fn partial_cmp(&self, other: &Self) -> Option { +impl<'a, T, BoundSelf, BoundRhs> PartialEq> + for BoundedSlice<'a, T, BoundSelf> +where + T: PartialEq, + BoundSelf: Get, + BoundRhs: Get, +{ + fn eq(&self, other: &BoundedSlice<'a, T, BoundRhs>) -> bool { + self.0 == other.0 + } +} + +impl<'a, T, BoundSelf, BoundRhs> PartialEq> + for BoundedSlice<'a, T, BoundSelf> +where + T: PartialEq, + BoundSelf: Get, + BoundRhs: Get, +{ + fn eq(&self, other: &BoundedVec) -> bool { + self.0 == other.0 + } +} + +impl<'a, T, BoundSelf, BoundRhs> PartialEq> + for BoundedSlice<'a, T, BoundSelf> +where + T: PartialEq, + BoundSelf: Get, + BoundRhs: Get, +{ + fn eq(&self, other: &WeakBoundedVec) -> bool { + self.0 == other.0 + } +} + +impl<'a, T, S: Get> Eq for BoundedSlice<'a, T, S> where T: Eq {} + +impl<'a, T, BoundSelf, BoundRhs> PartialOrd> + for BoundedSlice<'a, T, BoundSelf> +where + T: PartialOrd, + BoundSelf: Get, + BoundRhs: Get, +{ + fn partial_cmp(&self, other: &BoundedSlice<'a, T, BoundRhs>) -> Option { self.0.partial_cmp(&other.0) } } +impl<'a, T, BoundSelf, BoundRhs> PartialOrd> + for BoundedSlice<'a, T, BoundSelf> +where + T: PartialOrd, + BoundSelf: Get, + BoundRhs: Get, +{ + fn partial_cmp(&self, other: &BoundedVec) -> Option { + self.0.partial_cmp(&*other.0) + } +} + +impl<'a, T, BoundSelf, BoundRhs> PartialOrd> + for BoundedSlice<'a, T, BoundSelf> +where + T: PartialOrd, + BoundSelf: Get, + BoundRhs: Get, +{ + fn partial_cmp(&self, other: &WeakBoundedVec) -> Option { + self.0.partial_cmp(&*other.0) + } +} + impl<'a, T: Ord, Bound: Get> Ord for BoundedSlice<'a, T, Bound> { fn cmp(&self, other: &Self) -> sp_std::cmp::Ordering { self.0.cmp(&other.0) @@ -641,7 +709,29 @@ where BoundRhs: Get, { fn eq(&self, rhs: &BoundedVec) -> bool { - BoundSelf::get() == BoundRhs::get() && self.0 == rhs.0 + self.0 == rhs.0 + } +} + +impl PartialEq> for BoundedVec +where + T: PartialEq, + BoundSelf: Get, + BoundRhs: Get, +{ + fn eq(&self, rhs: &WeakBoundedVec) -> bool { + self.0 == rhs.0 + } +} + +impl<'a, T, BoundSelf, BoundRhs> PartialEq> for BoundedVec +where + T: PartialEq, + BoundSelf: Get, + BoundRhs: Get, +{ + fn eq(&self, rhs: &BoundedSlice<'a, T, BoundRhs>) -> bool { + self.0 == rhs.0 } } @@ -653,12 +743,39 @@ impl> PartialEq> for BoundedVec { impl> Eq for BoundedVec where T: Eq {} -impl> PartialOrd for BoundedVec { - fn partial_cmp(&self, other: &Self) -> Option { +impl PartialOrd> for BoundedVec +where + T: PartialOrd, + BoundSelf: Get, + BoundRhs: Get, +{ + fn partial_cmp(&self, other: &BoundedVec) -> Option { self.0.partial_cmp(&other.0) } } +impl PartialOrd> for BoundedVec +where + T: PartialOrd, + BoundSelf: Get, + BoundRhs: Get, +{ + fn partial_cmp(&self, other: &WeakBoundedVec) -> Option { + self.0.partial_cmp(&other.0) + } +} + +impl<'a, T, BoundSelf, BoundRhs> PartialOrd> for BoundedVec +where + T: PartialOrd, + BoundSelf: Get, + BoundRhs: Get, +{ + fn partial_cmp(&self, other: &BoundedSlice<'a, T, BoundRhs>) -> Option { + (&*self.0).partial_cmp(other.0) + } +} + impl> Ord for BoundedVec { fn cmp(&self, other: &Self) -> sp_std::cmp::Ordering { self.0.cmp(&other.0) diff --git a/primitives/runtime/src/bounded/weak_bounded_vec.rs b/primitives/runtime/src/bounded/weak_bounded_vec.rs index 0c0857c12be9a..82bae4118f13e 100644 --- a/primitives/runtime/src/bounded/weak_bounded_vec.rs +++ b/primitives/runtime/src/bounded/weak_bounded_vec.rs @@ -18,6 +18,7 @@ //! Traits, types and structs to support putting a bounded vector into storage, as a raw value, map //! or a double map. +use super::{BoundedSlice, BoundedVec}; use crate::traits::Get; use codec::{Decode, Encode, MaxEncodedLen}; use core::{ @@ -35,7 +36,7 @@ use sp_std::{marker::PhantomData, prelude::*}; /// is accepted, and some method allow to bypass the restriction with warnings. #[derive(Encode, scale_info::TypeInfo)] #[scale_info(skip_type_params(S))] -pub struct WeakBoundedVec(Vec, PhantomData); +pub struct WeakBoundedVec(pub(super) Vec, PhantomData); impl> Decode for WeakBoundedVec { fn decode(input: &mut I) -> Result { @@ -283,14 +284,36 @@ impl codec::DecodeLength for WeakBoundedVec { } } -// NOTE: we could also implement this as: -// impl, S2: Get> PartialEq> for WeakBoundedVec to allow comparison of bounded vectors with different bounds. -impl PartialEq for WeakBoundedVec +impl PartialEq> for WeakBoundedVec where T: PartialEq, + BoundSelf: Get, + BoundRhs: Get, { - fn eq(&self, rhs: &Self) -> bool { + fn eq(&self, rhs: &WeakBoundedVec) -> bool { + self.0 == rhs.0 + } +} + +impl PartialEq> for WeakBoundedVec +where + T: PartialEq, + BoundSelf: Get, + BoundRhs: Get, +{ + fn eq(&self, rhs: &BoundedVec) -> bool { + self.0 == rhs.0 + } +} + +impl<'a, T, BoundSelf, BoundRhs> PartialEq> + for WeakBoundedVec +where + T: PartialEq, + BoundSelf: Get, + BoundRhs: Get, +{ + fn eq(&self, rhs: &BoundedSlice<'a, T, BoundRhs>) -> bool { self.0 == rhs.0 } } @@ -301,14 +324,43 @@ impl> PartialEq> for WeakBoundedVec { } } -impl Eq for WeakBoundedVec where T: Eq {} +impl> Eq for WeakBoundedVec where T: Eq {} -impl> PartialOrd for WeakBoundedVec { - fn partial_cmp(&self, other: &Self) -> Option { +impl PartialOrd> + for WeakBoundedVec +where + T: PartialOrd, + BoundSelf: Get, + BoundRhs: Get, +{ + fn partial_cmp(&self, other: &WeakBoundedVec) -> Option { self.0.partial_cmp(&other.0) } } +impl PartialOrd> for WeakBoundedVec +where + T: PartialOrd, + BoundSelf: Get, + BoundRhs: Get, +{ + fn partial_cmp(&self, other: &BoundedVec) -> Option { + self.0.partial_cmp(&other.0) + } +} + +impl<'a, T, BoundSelf, BoundRhs> PartialOrd> + for WeakBoundedVec +where + T: PartialOrd, + BoundSelf: Get, + BoundRhs: Get, +{ + fn partial_cmp(&self, other: &BoundedSlice<'a, T, BoundRhs>) -> Option { + (&*self.0).partial_cmp(other.0) + } +} + impl> Ord for WeakBoundedVec { fn cmp(&self, other: &Self) -> sp_std::cmp::Ordering { self.0.cmp(&other.0) From 92c7be8244040a5fde6bc9ca806e1bcbda8fe094 Mon Sep 17 00:00:00 2001 From: Keith Yeung Date: Mon, 13 Jun 2022 17:26:54 +0200 Subject: [PATCH 3/4] cargo fmt --- primitives/runtime/src/bounded/bounded_vec.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/primitives/runtime/src/bounded/bounded_vec.rs b/primitives/runtime/src/bounded/bounded_vec.rs index 9cdcce9711541..531fb3490245d 100644 --- a/primitives/runtime/src/bounded/bounded_vec.rs +++ b/primitives/runtime/src/bounded/bounded_vec.rs @@ -724,7 +724,8 @@ where } } -impl<'a, T, BoundSelf, BoundRhs> PartialEq> for BoundedVec +impl<'a, T, BoundSelf, BoundRhs> PartialEq> + for BoundedVec where T: PartialEq, BoundSelf: Get, @@ -765,7 +766,8 @@ where } } -impl<'a, T, BoundSelf, BoundRhs> PartialOrd> for BoundedVec +impl<'a, T, BoundSelf, BoundRhs> PartialOrd> + for BoundedVec where T: PartialOrd, BoundSelf: Get, From a5d1b7dfc09a09e320b75872e019a60cdc2c4de5 Mon Sep 17 00:00:00 2001 From: Keith Yeung Date: Mon, 13 Jun 2022 18:09:48 +0200 Subject: [PATCH 4/4] Fixes --- primitives/runtime/src/bounded/bounded_vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/runtime/src/bounded/bounded_vec.rs b/primitives/runtime/src/bounded/bounded_vec.rs index 531fb3490245d..9231c83fc7675 100644 --- a/primitives/runtime/src/bounded/bounded_vec.rs +++ b/primitives/runtime/src/bounded/bounded_vec.rs @@ -163,7 +163,7 @@ where BoundRhs: Get, { fn partial_cmp(&self, other: &BoundedSlice<'a, T, BoundRhs>) -> Option { - self.0.partial_cmp(&other.0) + self.0.partial_cmp(other.0) } }