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

Move Get and bounded types to sp-core #12203

Merged
merged 4 commits into from
Sep 7, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

//! Traits, types and structs to support a bounded BTreeMap.

use crate::traits::{Get, TryCollect};
use crate::{Get, TryCollect};
use codec::{Decode, Encode, MaxEncodedLen};
use sp_std::{borrow::Borrow, collections::btree_map::BTreeMap, marker::PhantomData, ops::Deref};

Expand Down Expand Up @@ -363,7 +363,7 @@ where
#[cfg(test)]
pub mod test {
use super::*;
use crate::traits::ConstU32;
use crate::ConstU32;

fn map_from_keys<K>(keys: &[K]) -> BTreeMap<K, ()>
where
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

//! Traits, types and structs to support a bounded `BTreeSet`.

use crate::traits::{Get, TryCollect};
use crate::{Get, TryCollect};
use codec::{Decode, Encode, MaxEncodedLen};
use sp_std::{borrow::Borrow, collections::btree_set::BTreeSet, marker::PhantomData, ops::Deref};

Expand Down Expand Up @@ -321,7 +321,7 @@ where
#[cfg(test)]
pub mod test {
use super::*;
use crate::traits::ConstU32;
use crate::ConstU32;

fn set_from_keys<T>(keys: &[T]) -> BTreeSet<T>
where
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
//! or a double map.

use super::WeakBoundedVec;
use crate::traits::{Get, TryCollect};
use crate::{Get, TryCollect};
use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};
use core::{
ops::{Deref, Index, IndexMut, RangeBounds},
Expand Down Expand Up @@ -884,7 +884,7 @@ where
#[cfg(test)]
pub mod test {
use super::*;
use crate::{bounded_vec, traits::ConstU32};
use crate::{bounded_vec, ConstU32};

#[test]
fn slide_works() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
//! or a double map.

use super::{BoundedSlice, BoundedVec};
use crate::traits::Get;
use crate::Get;
use codec::{Decode, Encode, MaxEncodedLen};
use core::{
ops::{Deref, Index, IndexMut},
Expand Down Expand Up @@ -453,7 +453,7 @@ where
#[cfg(test)]
pub mod test {
use super::*;
use crate::traits::ConstU32;
use crate::ConstU32;

#[test]
fn bound_returns_correct_value() {
Expand Down
237 changes: 237 additions & 0 deletions primitives/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ pub mod hashing;

#[cfg(feature = "full_crypto")]
pub use hashing::{blake2_128, blake2_256, keccak_256, twox_128, twox_256, twox_64};
pub mod bounded;
pub mod crypto;
pub mod hexdisplay;

Expand Down Expand Up @@ -466,3 +467,239 @@ macro_rules! impl_maybe_marker {
// The maximum possible allocation size was chosen rather arbitrary, 32 MiB should be enough for
// everybody.
pub const MAX_POSSIBLE_ALLOCATION: u32 = 33554432; // 2^25 bytes, 32 MiB

/// A trait for querying a single value from a type defined in the trait.
///
/// It is not required that the value is constant.
pub trait TypedGet {
/// The type which is returned.
type Type;
/// Return the current value.
fn get() -> Self::Type;
}

/// A trait for querying a single value from a type.
///
/// It is not required that the value is constant.
pub trait Get<T> {
/// Return the current value.
fn get() -> T;
}

impl<T: Default> Get<T> for () {
fn get() -> T {
T::default()
}
}

/// Implement Get by returning Default for any type that implements Default.
pub struct GetDefault;
impl<T: Default> Get<T> for GetDefault {
fn get() -> T {
T::default()
}
}

macro_rules! impl_const_get {
($name:ident, $t:ty) => {
#[doc = "Const getter for a basic type."]
#[derive($crate::RuntimeDebug)]
pub struct $name<const T: $t>;
impl<const T: $t> Get<$t> for $name<T> {
fn get() -> $t {
T
}
}
impl<const T: $t> Get<Option<$t>> for $name<T> {
fn get() -> Option<$t> {
Some(T)
}
}
impl<const T: $t> TypedGet for $name<T> {
type Type = $t;
fn get() -> $t {
T
}
}
};
}

impl_const_get!(ConstBool, bool);
impl_const_get!(ConstU8, u8);
impl_const_get!(ConstU16, u16);
impl_const_get!(ConstU32, u32);
impl_const_get!(ConstU64, u64);
impl_const_get!(ConstU128, u128);
impl_const_get!(ConstI8, i8);
impl_const_get!(ConstI16, i16);
impl_const_get!(ConstI32, i32);
impl_const_get!(ConstI64, i64);
impl_const_get!(ConstI128, i128);

/// Try and collect into a collection `C`.
pub trait TryCollect<C> {
/// The error type that gets returned when a collection can't be made from `self`.
type Error;
/// Consume self and try to collect the results into `C`.
///
/// This is useful in preventing the undesirable `.collect().try_into()` call chain on
/// collections that need to be converted into a bounded type (e.g. `BoundedVec`).
fn try_collect(self) -> Result<C, Self::Error>;
}

/// Create new implementations of the [`Get`](crate::traits::Get) trait.
///
/// The so-called parameter type can be created in four different ways:
///
/// - Using `const` to create a parameter type that provides a `const` getter. It is required that
/// the `value` is const.
///
/// - Declare the parameter type without `const` to have more freedom when creating the value.
///
/// NOTE: A more substantial version of this macro is available in `frame_support` crate which
/// allows mutable and persistant variants.
///
/// # Examples
///
/// ```
/// # use sp_core::Get;
/// # use sp_core::parameter_types;
/// // This function cannot be used in a const context.
/// fn non_const_expression() -> u64 { 99 }
///
/// const FIXED_VALUE: u64 = 10;
/// parameter_types! {
/// pub const Argument: u64 = 42 + FIXED_VALUE;
/// /// Visibility of the type is optional
/// OtherArgument: u64 = non_const_expression();
/// }
///
/// trait Config {
/// type Parameter: Get<u64>;
/// type OtherParameter: Get<u64>;
/// }
///
/// struct Runtime;
/// impl Config for Runtime {
/// type Parameter = Argument;
/// type OtherParameter = OtherArgument;
/// }
/// ```
///
/// # Invalid example:
///
/// ```compile_fail
/// # use sp_core::Get;
/// # use sp_core::parameter_types;
/// // This function cannot be used in a const context.
/// fn non_const_expression() -> u64 { 99 }
///
/// parameter_types! {
/// pub const Argument: u64 = non_const_expression();
/// }
/// ```
#[macro_export]
macro_rules! parameter_types {
(
$( #[ $attr:meta ] )*
$vis:vis const $name:ident: $type:ty = $value:expr;
$( $rest:tt )*
) => (
$( #[ $attr ] )*
$vis struct $name;
$crate::parameter_types!(@IMPL_CONST $name , $type , $value);
$crate::parameter_types!( $( $rest )* );
);
(
$( #[ $attr:meta ] )*
$vis:vis $name:ident: $type:ty = $value:expr;
$( $rest:tt )*
) => (
$( #[ $attr ] )*
$vis struct $name;
$crate::parameter_types!(@IMPL $name, $type, $value);
$crate::parameter_types!( $( $rest )* );
);
() => ();
(@IMPL_CONST $name:ident, $type:ty, $value:expr) => {
impl $name {
/// Returns the value of this parameter type.
pub const fn get() -> $type {
$value
}
}

impl<I: From<$type>> $crate::Get<I> for $name {
fn get() -> I {
I::from(Self::get())
}
}

impl $crate::TypedGet for $name {
type Type = $type;
fn get() -> $type {
Self::get()
}
}
};
(@IMPL $name:ident, $type:ty, $value:expr) => {
impl $name {
/// Returns the value of this parameter type.
pub fn get() -> $type {
$value
}
}

impl<I: From<$type>> $crate::Get<I> for $name {
fn get() -> I {
I::from(Self::get())
}
}

impl $crate::TypedGet for $name {
type Type = $type;
fn get() -> $type {
Self::get()
}
}
};
}

/// Build a bounded vec from the given literals.
///
/// The type of the outcome must be known.
///
/// Will not handle any errors and just panic if the given literals cannot fit in the corresponding
/// bounded vec type. Thus, this is only suitable for testing and non-consensus code.
#[macro_export]
#[cfg(feature = "std")]
macro_rules! bounded_vec {
($ ($values:expr),* $(,)?) => {
{
$crate::sp_std::vec![$($values),*].try_into().unwrap()
}
};
( $value:expr ; $repetition:expr ) => {
{
$crate::sp_std::vec![$value ; $repetition].try_into().unwrap()
}
}
}

/// Build a bounded btree-map from the given literals.
///
/// The type of the outcome must be known.
///
/// Will not handle any errors and just panic if the given literals cannot fit in the corresponding
/// bounded vec type. Thus, this is only suitable for testing and non-consensus code.
#[macro_export]
#[cfg(feature = "std")]
macro_rules! bounded_btree_map {
($ ( $key:expr => $value:expr ),* $(,)?) => {
{
$crate::TryCollect::<$crate::BoundedBTreeMap<_, _, _>>::try_collect(
$crate::sp_std::vec![$(($key, $value)),*].into_iter()
).unwrap()
}
};
}
47 changes: 4 additions & 43 deletions primitives/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ use sp_std::prelude::*;
use codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;

pub mod bounded;
pub mod curve;
pub mod generic;
pub mod legacy;
Expand All @@ -70,9 +69,6 @@ pub mod transaction_validity;

pub use crate::runtime_string::*;

// Re-export bounded types
pub use bounded::{BoundedBTreeMap, BoundedBTreeSet, BoundedSlice, BoundedVec, WeakBoundedVec};

// Re-export Multiaddress
pub use multiaddress::MultiAddress;

Expand All @@ -82,9 +78,13 @@ pub use generic::{Digest, DigestItem};
pub use sp_application_crypto::{BoundToRuntimeAppPublic, RuntimeAppPublic};
/// Re-export this since it's part of the API of this crate.
pub use sp_core::{
bounded::{BoundedBTreeMap, BoundedBTreeSet, BoundedSlice, BoundedVec, WeakBoundedVec},
crypto::{key_types, AccountId32, CryptoType, CryptoTypeId, KeyTypeId},
TypeId,
};
/// Re-export bounded_vec and bounded_btree_map macros only when std is enabled.
#[cfg(feature = "std")]
pub use sp_core::{bounded_btree_map, bounded_vec};

/// Re-export `RuntimeDebug`, to avoid dependency clutter.
pub use sp_core::RuntimeDebug;
Expand Down Expand Up @@ -834,45 +834,6 @@ macro_rules! assert_eq_error_rate {
};
}

/// Build a bounded vec from the given literals.
///
/// The type of the outcome must be known.
///
/// Will not handle any errors and just panic if the given literals cannot fit in the corresponding
/// bounded vec type. Thus, this is only suitable for testing and non-consensus code.
#[macro_export]
#[cfg(feature = "std")]
macro_rules! bounded_vec {
($ ($values:expr),* $(,)?) => {
{
$crate::sp_std::vec![$($values),*].try_into().unwrap()
}
};
( $value:expr ; $repetition:expr ) => {
{
$crate::sp_std::vec![$value ; $repetition].try_into().unwrap()
}
}
}

/// Build a bounded btree-map from the given literals.
///
/// The type of the outcome must be known.
///
/// Will not handle any errors and just panic if the given literals cannot fit in the corresponding
/// bounded vec type. Thus, this is only suitable for testing and non-consensus code.
#[macro_export]
#[cfg(feature = "std")]
macro_rules! bounded_btree_map {
($ ( $key:expr => $value:expr ),* $(,)?) => {
{
$crate::traits::TryCollect::<$crate::BoundedBTreeMap<_, _, _>>::try_collect(
$crate::sp_std::vec![$(($key, $value)),*].into_iter()
).unwrap()
}
};
}

/// Simple blob to hold an extrinsic without committing to its format and ensure it is serialized
/// correctly.
#[derive(PartialEq, Eq, Clone, Default, Encode, Decode, TypeInfo)]
Expand Down
Loading