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

Commit

Permalink
Move Get and bounded types to sp-core (#12203)
Browse files Browse the repository at this point in the history
* Move Get and bounded types to sp-core

* Fixes

* cargo fmt

* Fixes
  • Loading branch information
KiChjang authored Sep 7, 2022
1 parent 021f712 commit 5e2ffeb
Show file tree
Hide file tree
Showing 8 changed files with 254 additions and 248 deletions.
File renamed without changes.
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::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::bounded::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

0 comments on commit 5e2ffeb

Please sign in to comment.