Implement PartialOrd and Ord on BoundedSlice and WeakBoundedVec (#11655)

* Implement PartialOrd and Ord on BoundedSlice and WeakBoundedVec

* More implementations of PartialEq and PartialOrd

* cargo fmt

* Fixes
This commit is contained in:
Keith Yeung
2022-06-13 22:55:48 +02:00
committed by GitHub
parent 4e2fb0af60
commit 19684de7d8
4 changed files with 221 additions and 18 deletions
@@ -66,6 +66,11 @@ where
K: Ord,
S: Get<u32>,
{
/// Create `Self` from `t` without any checks.
fn unchecked_from(t: BTreeMap<K, V>) -> 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::<K, V, Bound>::try_from(self.collect::<BTreeMap<K, V>>())
.expect("length checked above; qed"))
Ok(BoundedBTreeMap::<K, V, Bound>::unchecked_from(self.collect::<BTreeMap<K, V>>()))
}
}
}
@@ -65,6 +65,11 @@ where
T: Ord,
S: Get<u32>,
{
/// Create `Self` from `t` without any checks.
fn unchecked_from(t: BTreeSet<T>) -> 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::<T, Bound>::try_from(self.collect::<BTreeSet<T>>())
.expect("length is checked above; qed"))
Ok(BoundedBTreeSet::<T, Bound>::unchecked_from(self.collect::<BTreeSet<T>>()))
}
}
}
@@ -43,7 +43,7 @@ use sp_std::{marker::PhantomData, prelude::*};
#[derive(Encode, scale_info::TypeInfo)]
#[scale_info(skip_type_params(S))]
pub struct BoundedVec<T, S>(
Vec<T>,
pub(super) Vec<T>,
#[cfg_attr(feature = "std", serde(skip_serializing))] PhantomData<S>,
);
@@ -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<S>);
pub struct BoundedSlice<'a, T, S>(pub(super) &'a [T], PhantomData<S>);
// `BoundedSlice`s encode to something which will always decode into a `BoundedVec`,
// `WeakBoundedVec`, or a `Vec`.
@@ -117,13 +117,81 @@ impl<'a, T: Encode + Decode, S: Get<u32>> EncodeLike<WeakBoundedVec<T, S>>
}
impl<'a, T: Encode + Decode, S: Get<u32>> EncodeLike<Vec<T>> for BoundedSlice<'a, T, S> {}
impl<T: PartialOrd, Bound: Get<u32>> PartialOrd for BoundedVec<T, Bound> {
fn partial_cmp(&self, other: &Self) -> Option<sp_std::cmp::Ordering> {
self.0.partial_cmp(&other.0)
impl<'a, T, BoundSelf, BoundRhs> PartialEq<BoundedSlice<'a, T, BoundRhs>>
for BoundedSlice<'a, T, BoundSelf>
where
T: PartialEq,
BoundSelf: Get<u32>,
BoundRhs: Get<u32>,
{
fn eq(&self, other: &BoundedSlice<'a, T, BoundRhs>) -> bool {
self.0 == other.0
}
}
impl<T: Ord, Bound: Get<u32>> Ord for BoundedVec<T, Bound> {
impl<'a, T, BoundSelf, BoundRhs> PartialEq<BoundedVec<T, BoundRhs>>
for BoundedSlice<'a, T, BoundSelf>
where
T: PartialEq,
BoundSelf: Get<u32>,
BoundRhs: Get<u32>,
{
fn eq(&self, other: &BoundedVec<T, BoundRhs>) -> bool {
self.0 == other.0
}
}
impl<'a, T, BoundSelf, BoundRhs> PartialEq<WeakBoundedVec<T, BoundRhs>>
for BoundedSlice<'a, T, BoundSelf>
where
T: PartialEq,
BoundSelf: Get<u32>,
BoundRhs: Get<u32>,
{
fn eq(&self, other: &WeakBoundedVec<T, BoundRhs>) -> bool {
self.0 == other.0
}
}
impl<'a, T, S: Get<u32>> Eq for BoundedSlice<'a, T, S> where T: Eq {}
impl<'a, T, BoundSelf, BoundRhs> PartialOrd<BoundedSlice<'a, T, BoundRhs>>
for BoundedSlice<'a, T, BoundSelf>
where
T: PartialOrd,
BoundSelf: Get<u32>,
BoundRhs: Get<u32>,
{
fn partial_cmp(&self, other: &BoundedSlice<'a, T, BoundRhs>) -> Option<sp_std::cmp::Ordering> {
self.0.partial_cmp(other.0)
}
}
impl<'a, T, BoundSelf, BoundRhs> PartialOrd<BoundedVec<T, BoundRhs>>
for BoundedSlice<'a, T, BoundSelf>
where
T: PartialOrd,
BoundSelf: Get<u32>,
BoundRhs: Get<u32>,
{
fn partial_cmp(&self, other: &BoundedVec<T, BoundRhs>) -> Option<sp_std::cmp::Ordering> {
self.0.partial_cmp(&*other.0)
}
}
impl<'a, T, BoundSelf, BoundRhs> PartialOrd<WeakBoundedVec<T, BoundRhs>>
for BoundedSlice<'a, T, BoundSelf>
where
T: PartialOrd,
BoundSelf: Get<u32>,
BoundRhs: Get<u32>,
{
fn partial_cmp(&self, other: &WeakBoundedVec<T, BoundRhs>) -> Option<sp_std::cmp::Ordering> {
self.0.partial_cmp(&*other.0)
}
}
impl<'a, T: Ord, Bound: Get<u32>> Ord for BoundedSlice<'a, T, Bound> {
fn cmp(&self, other: &Self) -> sp_std::cmp::Ordering {
self.0.cmp(&other.0)
}
@@ -650,7 +718,30 @@ where
BoundRhs: Get<u32>,
{
fn eq(&self, rhs: &BoundedVec<T, BoundRhs>) -> bool {
BoundSelf::get() == BoundRhs::get() && self.0 == rhs.0
self.0 == rhs.0
}
}
impl<T, BoundSelf, BoundRhs> PartialEq<WeakBoundedVec<T, BoundRhs>> for BoundedVec<T, BoundSelf>
where
T: PartialEq,
BoundSelf: Get<u32>,
BoundRhs: Get<u32>,
{
fn eq(&self, rhs: &WeakBoundedVec<T, BoundRhs>) -> bool {
self.0 == rhs.0
}
}
impl<'a, T, BoundSelf, BoundRhs> PartialEq<BoundedSlice<'a, T, BoundRhs>>
for BoundedVec<T, BoundSelf>
where
T: PartialEq,
BoundSelf: Get<u32>,
BoundRhs: Get<u32>,
{
fn eq(&self, rhs: &BoundedSlice<'a, T, BoundRhs>) -> bool {
self.0 == rhs.0
}
}
@@ -662,6 +753,46 @@ impl<T: PartialEq, S: Get<u32>> PartialEq<Vec<T>> for BoundedVec<T, S> {
impl<T, S: Get<u32>> Eq for BoundedVec<T, S> where T: Eq {}
impl<T, BoundSelf, BoundRhs> PartialOrd<BoundedVec<T, BoundRhs>> for BoundedVec<T, BoundSelf>
where
T: PartialOrd,
BoundSelf: Get<u32>,
BoundRhs: Get<u32>,
{
fn partial_cmp(&self, other: &BoundedVec<T, BoundRhs>) -> Option<sp_std::cmp::Ordering> {
self.0.partial_cmp(&other.0)
}
}
impl<T, BoundSelf, BoundRhs> PartialOrd<WeakBoundedVec<T, BoundRhs>> for BoundedVec<T, BoundSelf>
where
T: PartialOrd,
BoundSelf: Get<u32>,
BoundRhs: Get<u32>,
{
fn partial_cmp(&self, other: &WeakBoundedVec<T, BoundRhs>) -> Option<sp_std::cmp::Ordering> {
self.0.partial_cmp(&other.0)
}
}
impl<'a, T, BoundSelf, BoundRhs> PartialOrd<BoundedSlice<'a, T, BoundRhs>>
for BoundedVec<T, BoundSelf>
where
T: PartialOrd,
BoundSelf: Get<u32>,
BoundRhs: Get<u32>,
{
fn partial_cmp(&self, other: &BoundedSlice<'a, T, BoundRhs>) -> Option<sp_std::cmp::Ordering> {
(&*self.0).partial_cmp(other.0)
}
}
impl<T: Ord, Bound: Get<u32>> Ord for BoundedVec<T, Bound> {
fn cmp(&self, other: &Self) -> sp_std::cmp::Ordering {
self.0.cmp(&other.0)
}
}
impl<T, S> MaxEncodedLen for BoundedVec<T, S>
where
T: MaxEncodedLen,
@@ -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<T, S>(Vec<T>, PhantomData<S>);
pub struct WeakBoundedVec<T, S>(pub(super) Vec<T>, PhantomData<S>);
impl<T: Decode, S: Get<u32>> Decode for WeakBoundedVec<T, S> {
fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
@@ -283,14 +284,36 @@ impl<T, S> codec::DecodeLength for WeakBoundedVec<T, S> {
}
}
// NOTE: we could also implement this as:
// impl<T: Value, S1: Get<u32>, S2: Get<u32>> PartialEq<WeakBoundedVec<T, S2>> for WeakBoundedVec<T,
// S1> to allow comparison of bounded vectors with different bounds.
impl<T, S> PartialEq for WeakBoundedVec<T, S>
impl<T, BoundSelf, BoundRhs> PartialEq<WeakBoundedVec<T, BoundRhs>> for WeakBoundedVec<T, BoundSelf>
where
T: PartialEq,
BoundSelf: Get<u32>,
BoundRhs: Get<u32>,
{
fn eq(&self, rhs: &Self) -> bool {
fn eq(&self, rhs: &WeakBoundedVec<T, BoundRhs>) -> bool {
self.0 == rhs.0
}
}
impl<T, BoundSelf, BoundRhs> PartialEq<BoundedVec<T, BoundRhs>> for WeakBoundedVec<T, BoundSelf>
where
T: PartialEq,
BoundSelf: Get<u32>,
BoundRhs: Get<u32>,
{
fn eq(&self, rhs: &BoundedVec<T, BoundRhs>) -> bool {
self.0 == rhs.0
}
}
impl<'a, T, BoundSelf, BoundRhs> PartialEq<BoundedSlice<'a, T, BoundRhs>>
for WeakBoundedVec<T, BoundSelf>
where
T: PartialEq,
BoundSelf: Get<u32>,
BoundRhs: Get<u32>,
{
fn eq(&self, rhs: &BoundedSlice<'a, T, BoundRhs>) -> bool {
self.0 == rhs.0
}
}
@@ -301,7 +324,48 @@ impl<T: PartialEq, S: Get<u32>> PartialEq<Vec<T>> for WeakBoundedVec<T, S> {
}
}
impl<T, S> Eq for WeakBoundedVec<T, S> where T: Eq {}
impl<T, S: Get<u32>> Eq for WeakBoundedVec<T, S> where T: Eq {}
impl<T, BoundSelf, BoundRhs> PartialOrd<WeakBoundedVec<T, BoundRhs>>
for WeakBoundedVec<T, BoundSelf>
where
T: PartialOrd,
BoundSelf: Get<u32>,
BoundRhs: Get<u32>,
{
fn partial_cmp(&self, other: &WeakBoundedVec<T, BoundRhs>) -> Option<sp_std::cmp::Ordering> {
self.0.partial_cmp(&other.0)
}
}
impl<T, BoundSelf, BoundRhs> PartialOrd<BoundedVec<T, BoundRhs>> for WeakBoundedVec<T, BoundSelf>
where
T: PartialOrd,
BoundSelf: Get<u32>,
BoundRhs: Get<u32>,
{
fn partial_cmp(&self, other: &BoundedVec<T, BoundRhs>) -> Option<sp_std::cmp::Ordering> {
self.0.partial_cmp(&other.0)
}
}
impl<'a, T, BoundSelf, BoundRhs> PartialOrd<BoundedSlice<'a, T, BoundRhs>>
for WeakBoundedVec<T, BoundSelf>
where
T: PartialOrd,
BoundSelf: Get<u32>,
BoundRhs: Get<u32>,
{
fn partial_cmp(&self, other: &BoundedSlice<'a, T, BoundRhs>) -> Option<sp_std::cmp::Ordering> {
(&*self.0).partial_cmp(other.0)
}
}
impl<T: Ord, S: Get<u32>> Ord for WeakBoundedVec<T, S> {
fn cmp(&self, other: &Self) -> sp_std::cmp::Ordering {
self.0.cmp(&other.0)
}
}
impl<T, S> MaxEncodedLen for WeakBoundedVec<T, S>
where