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

Implement PartialOrd and Ord on BoundedSlice and WeakBoundedVec #11655

Merged
merged 4 commits into from
Jun 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -641,7 +709,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 @@ -653,6 +744,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