Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
Implement PartialOrd and Ord on BoundedSlice and WeakBoundedVec (#11655)
Browse files Browse the repository at this point in the history
* Implement PartialOrd and Ord on BoundedSlice and WeakBoundedVec

* More implementations of PartialEq and PartialOrd

* cargo fmt

* Fixes
  • Loading branch information
KiChjang authored Jun 13, 2022
1 parent c8e2c4c commit 4c41a7b
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 18 deletions.
8 changes: 6 additions & 2 deletions primitives/runtime/src/bounded/bounded_btree_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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>>()))
}
}
}
Expand Down
8 changes: 6 additions & 2 deletions primitives/runtime/src/bounded/bounded_btree_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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>>()))
}
}
}
Expand Down
145 changes: 138 additions & 7 deletions primitives/runtime/src/bounded/bounded_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
);

Expand Down Expand Up @@ -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`.
Expand All @@ -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)
}
Expand Down Expand Up @@ -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
}
}

Expand All @@ -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,
Expand Down
78 changes: 71 additions & 7 deletions primitives/runtime/src/bounded/weak_bounded_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand All @@ -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> {
Expand Down Expand Up @@ -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
}
}
Expand All @@ -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
Expand Down

0 comments on commit 4c41a7b

Please sign in to comment.