diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 9664663..67dd411 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -110,10 +110,16 @@ jobs: command: check toolchain: stable args: --manifest-path ./frame-metadata/Cargo.toml --no-default-features --features v13 + - name: Checking v14 + uses: actions-rs/cargo@master + with: + command: check + toolchain: stable + args: --manifest-path ./frame-metadata/Cargo.toml --no-default-features --features v14 - name: Checking all versions uses: actions-rs/cargo@master with: command: check toolchain: stable - args: --manifest-path ./frame-metadata/Cargo.toml --no-default-features --features v12,v13 + args: --manifest-path ./frame-metadata/Cargo.toml --no-default-features --features v12,v13,v14 diff --git a/frame-metadata/Cargo.toml b/frame-metadata/Cargo.toml index 7c888c4..d4a8a22 100644 --- a/frame-metadata/Cargo.toml +++ b/frame-metadata/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "frame-metadata" -version = "12.0.0" +version = "14.0.0" authors = ["Parity Technologies "] edition = "2018" license = "Apache-2.0" @@ -19,9 +19,10 @@ scale-info = { version = "0.6.0", default-features = false, optional = true, fea serde = { version = "1.0.101", optional = true, features = ["derive"] } [features] -default = ["std", "v12"] +default = ["std", "v14"] v12 = [] -v13 = ["scale-info"] +v13 = [] +v14 = ["scale-info"] std = [ "codec/std", "scale-info/std", diff --git a/frame-metadata/src/decode_different.rs b/frame-metadata/src/decode_different.rs new file mode 100644 index 0000000..982ca6d --- /dev/null +++ b/frame-metadata/src/decode_different.rs @@ -0,0 +1,164 @@ +// This file is part of Substrate. + +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use codec::{Encode, Output}; + +cfg_if::cfg_if! { + if #[cfg(feature = "std")] { + use codec::{Decode, Error, Input}; + pub type StringBuf = String; + } else { + extern crate alloc; + use alloc::vec::Vec; + + /// On `no_std` we do not support `Decode` and thus `StringBuf` is just `&'static str`. + /// So, if someone tries to decode this stuff on `no_std`, they will get a compilation error. + pub type StringBuf = &'static str; + } +} + +/// A type that decodes to a different type than it encodes. +/// The user needs to make sure that both types use the same encoding. +/// +/// For example a `&'static [ &'static str ]` can be decoded to a `Vec`. +#[derive(Clone)] +pub enum DecodeDifferent +where + B: 'static, + O: 'static, +{ + Encode(B), + Decoded(O), +} + +impl Encode for DecodeDifferent +where + B: Encode + 'static, + O: Encode + 'static, +{ + fn encode_to(&self, dest: &mut W) { + match self { + DecodeDifferent::Encode(b) => b.encode_to(dest), + DecodeDifferent::Decoded(o) => o.encode_to(dest), + } + } +} + +impl codec::EncodeLike for DecodeDifferent +where + B: Encode + 'static, + O: Encode + 'static, +{ +} + +#[cfg(feature = "std")] +impl Decode for DecodeDifferent +where + B: 'static, + O: Decode + 'static, +{ + fn decode(input: &mut I) -> Result { + ::decode(input).map(|val| DecodeDifferent::Decoded(val)) + } +} + +impl PartialEq for DecodeDifferent +where + B: Encode + Eq + PartialEq + 'static, + O: Encode + Eq + PartialEq + 'static, +{ + fn eq(&self, other: &Self) -> bool { + self.encode() == other.encode() + } +} + +impl Eq for DecodeDifferent +where + B: Encode + Eq + PartialEq + 'static, + O: Encode + Eq + PartialEq + 'static, +{ +} + +impl core::fmt::Debug for DecodeDifferent +where + B: core::fmt::Debug + Eq + 'static, + O: core::fmt::Debug + Eq + 'static, +{ + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + match self { + DecodeDifferent::Encode(b) => b.fmt(f), + DecodeDifferent::Decoded(o) => o.fmt(f), + } + } +} + +#[cfg(feature = "std")] +impl serde::Serialize for DecodeDifferent +where + B: serde::Serialize + 'static, + O: serde::Serialize + 'static, +{ + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + match self { + DecodeDifferent::Encode(b) => b.serialize(serializer), + DecodeDifferent::Decoded(o) => o.serialize(serializer), + } + } +} + +pub type DecodeDifferentArray = DecodeDifferent<&'static [B], Vec>; + +pub type DecodeDifferentStr = DecodeDifferent<&'static str, StringBuf>; + +/// Newtype wrapper for support encoding functions (actual the result of the function). +#[derive(Clone, Eq)] +pub struct FnEncode(pub fn() -> E) +where + E: Encode + 'static; + +impl Encode for FnEncode { + fn encode_to(&self, dest: &mut W) { + self.0().encode_to(dest); + } +} + +impl codec::EncodeLike for FnEncode {} + +impl PartialEq for FnEncode { + fn eq(&self, other: &Self) -> bool { + self.0().eq(&other.0()) + } +} + +impl core::fmt::Debug for FnEncode { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + self.0().fmt(f) + } +} + +#[cfg(feature = "std")] +impl serde::Serialize for FnEncode { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.0().serialize(serializer) + } +} diff --git a/frame-metadata/src/lib.rs b/frame-metadata/src/lib.rs index 528b0a5..7784164 100644 --- a/frame-metadata/src/lib.rs +++ b/frame-metadata/src/lib.rs @@ -34,12 +34,18 @@ cfg_if::cfg_if! { use codec::{Encode, Output}; +#[cfg(any(feature = "v12", feature = "v13"))] +pub mod decode_different; + #[cfg(feature = "v12")] pub mod v12; #[cfg(feature = "v13")] pub mod v13; +#[cfg(feature = "v14")] +pub mod v14; + /// Metadata prefixed by a u32 for reserved usage #[derive(Eq, Encode, PartialEq)] #[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] @@ -93,6 +99,12 @@ pub enum RuntimeMetadata { /// Version 13 for runtime metadata, as raw encoded bytes. #[cfg(not(feature = "v13"))] V13(OpaqueMetadata), + /// Version 14 for runtime metadata. + #[cfg(feature = "v14")] + V14(v14::RuntimeMetadataV14), + /// Version 14 for runtime metadata, as raw encoded bytes. + #[cfg(not(feature = "v14"))] + V14(OpaqueMetadata), } /// Stores the encoded `RuntimeMetadata` as raw bytes. diff --git a/frame-metadata/src/v12.rs b/frame-metadata/src/v12.rs index 1a85672..be90094 100644 --- a/frame-metadata/src/v12.rs +++ b/frame-metadata/src/v12.rs @@ -15,13 +15,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Decodable variant of the RuntimeMetadata. - +use crate::decode_different::*; use codec::{Encode, Output}; cfg_if::cfg_if! { if #[cfg(feature = "std")] { - use codec::{Decode, Error, Input}; + use codec::Decode; use serde::Serialize; type StringBuf = String; @@ -35,108 +34,10 @@ cfg_if::cfg_if! { } } -use core::marker::PhantomData; - /// Current prefix of metadata pub const META_RESERVED: u32 = 0x6174656d; // 'meta' warn endianness -/// A type that decodes to a different type than it encodes. -/// The user needs to make sure that both types use the same encoding. -/// -/// For example a `&'static [ &'static str ]` can be decoded to a `Vec`. -#[derive(Clone)] -pub enum DecodeDifferent -where - B: 'static, - O: 'static, -{ - Encode(B), - Decoded(O), -} - -impl Encode for DecodeDifferent -where - B: Encode + 'static, - O: Encode + 'static, -{ - fn encode_to(&self, dest: &mut W) { - match self { - DecodeDifferent::Encode(b) => b.encode_to(dest), - DecodeDifferent::Decoded(o) => o.encode_to(dest), - } - } -} - -impl codec::EncodeLike for DecodeDifferent -where - B: Encode + 'static, - O: Encode + 'static, -{ -} - -#[cfg(feature = "std")] -impl Decode for DecodeDifferent -where - B: 'static, - O: Decode + 'static, -{ - fn decode(input: &mut I) -> Result { - ::decode(input).map(|val| DecodeDifferent::Decoded(val)) - } -} - -impl PartialEq for DecodeDifferent -where - B: Encode + Eq + PartialEq + 'static, - O: Encode + Eq + PartialEq + 'static, -{ - fn eq(&self, other: &Self) -> bool { - self.encode() == other.encode() - } -} - -impl Eq for DecodeDifferent -where - B: Encode + Eq + PartialEq + 'static, - O: Encode + Eq + PartialEq + 'static, -{ -} - -impl core::fmt::Debug for DecodeDifferent -where - B: core::fmt::Debug + Eq + 'static, - O: core::fmt::Debug + Eq + 'static, -{ - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - match self { - DecodeDifferent::Encode(b) => b.fmt(f), - DecodeDifferent::Decoded(o) => o.fmt(f), - } - } -} - -#[cfg(feature = "std")] -impl serde::Serialize for DecodeDifferent -where - B: serde::Serialize + 'static, - O: serde::Serialize + 'static, -{ - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - match self { - DecodeDifferent::Encode(b) => b.serialize(serializer), - DecodeDifferent::Decoded(o) => o.serialize(serializer), - } - } -} - -pub type DecodeDifferentArray = DecodeDifferent<&'static [B], Vec>; - -type DecodeDifferentStr = DecodeDifferent<&'static str, StringBuf>; - -/// All the metadata about a function. +/// Metadata about a function. #[derive(Clone, PartialEq, Eq, Encode)] #[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] pub struct FunctionMetadata { @@ -145,7 +46,7 @@ pub struct FunctionMetadata { pub documentation: DecodeDifferentArray<&'static str, StringBuf>, } -/// All the metadata about a function argument. +/// Metadata about a function argument. #[derive(Clone, PartialEq, Eq, Encode)] #[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] pub struct FunctionArgumentMetadata { @@ -153,43 +54,7 @@ pub struct FunctionArgumentMetadata { pub ty: DecodeDifferentStr, } -/// Newtype wrapper for support encoding functions (actual the result of the function). -#[derive(Clone, Eq)] -pub struct FnEncode(pub fn() -> E) -where - E: Encode + 'static; - -impl Encode for FnEncode { - fn encode_to(&self, dest: &mut W) { - self.0().encode_to(dest); - } -} - -impl codec::EncodeLike for FnEncode {} - -impl PartialEq for FnEncode { - fn eq(&self, other: &Self) -> bool { - self.0().eq(&other.0()) - } -} - -impl core::fmt::Debug for FnEncode { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - self.0().fmt(f) - } -} - -#[cfg(feature = "std")] -impl serde::Serialize for FnEncode { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - self.0().serialize(serializer) - } -} - -/// All the metadata about an outer event. +/// Metadata about an outer event. #[derive(Clone, PartialEq, Eq, Encode)] #[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] pub struct OuterEventMetadata { @@ -200,7 +65,7 @@ pub struct OuterEventMetadata { >, } -/// All the metadata about an event. +/// Metadata about an event. #[derive(Clone, PartialEq, Eq, Encode)] #[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] pub struct EventMetadata { @@ -209,7 +74,7 @@ pub struct EventMetadata { pub documentation: DecodeDifferentArray<&'static str, StringBuf>, } -/// All the metadata about one storage entry. +/// Metadata about one storage entry. #[derive(Clone, PartialEq, Eq, Encode)] #[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] pub struct StorageEntryMetadata { @@ -220,7 +85,7 @@ pub struct StorageEntryMetadata { pub documentation: DecodeDifferentArray<&'static str, StringBuf>, } -/// All the metadata about one module constant. +/// Metadata about one module constant. #[derive(Clone, PartialEq, Eq, Encode)] #[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] pub struct ModuleConstantMetadata { @@ -230,7 +95,7 @@ pub struct ModuleConstantMetadata { pub documentation: DecodeDifferentArray<&'static str, StringBuf>, } -/// All the metadata about a module error. +/// Metadata about a module error. #[derive(Clone, PartialEq, Eq, Encode)] #[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] pub struct ErrorMetadata { @@ -238,7 +103,7 @@ pub struct ErrorMetadata { pub documentation: DecodeDifferentArray<&'static str, StringBuf>, } -/// All the metadata about errors in a module. +/// Metadata about errors in a module. pub trait ModuleErrorMetadata { fn metadata() -> &'static [ErrorMetadata]; } @@ -359,18 +224,13 @@ pub struct ExtrinsicMetadata { /// The metadata of a runtime. #[derive(Eq, Encode, PartialEq)] #[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] -pub struct RuntimeMetadataV12 { +pub struct RuntimeMetadataV12 { /// Metadata of all the modules. pub modules: DecodeDifferentArray, /// Metadata of the extrinsic. pub extrinsic: ExtrinsicMetadata, - /// Marker for dummy type parameter required by v13 but not used here. - pub marker: PhantomData, } -/// The latest version of the metadata. -pub type RuntimeMetadataLastVersion = RuntimeMetadataV12; - /// All metadata about an runtime module. #[derive(Clone, PartialEq, Eq, Encode)] #[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] diff --git a/frame-metadata/src/v13.rs b/frame-metadata/src/v13.rs index 8f8a1a0..800f1a3 100644 --- a/frame-metadata/src/v13.rs +++ b/frame-metadata/src/v13.rs @@ -1,6 +1,6 @@ // This file is part of Substrate. -// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// Copyright (C) 2018-2021 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,212 +15,148 @@ // See the License for the specific language governing permissions and // limitations under the License. +use crate::decode_different::*; +use codec::{Encode, Output}; + cfg_if::cfg_if! { if #[cfg(feature = "std")] { use codec::Decode; use serde::Serialize; + } else { + extern crate alloc; + use alloc::vec::Vec; } } -use super::RuntimeMetadataPrefixed; -use codec::Encode; -use scale_info::prelude::vec::Vec; -use scale_info::{ - form::{Form, MetaForm, PortableForm}, - meta_type, IntoPortable, PortableRegistry, Registry, TypeInfo, -}; - /// Current prefix of metadata pub const META_RESERVED: u32 = 0x6174656d; // 'meta' warn endianness -/// Type alias placeholder for `ByteGetter` equivalent. todo: [AJ] figure out what to do here -pub type ByteGetter = Vec; - -pub type RuntimeMetadataLastVersion = RuntimeMetadataV13; - -impl From for super::RuntimeMetadataPrefixed { - fn from(metadata: RuntimeMetadataLastVersion) -> RuntimeMetadataPrefixed { - RuntimeMetadataPrefixed(META_RESERVED, super::RuntimeMetadata::V13(metadata)) - } +/// Metadata about a function. +#[derive(Clone, PartialEq, Eq, Encode, Debug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub struct FunctionMetadata { + pub name: DecodeDifferentStr, + pub arguments: DecodeDifferentArray, + pub documentation: DecodeDifferentArray<&'static str, StringBuf>, +} + +/// Metadata about a function argument. +#[derive(Clone, PartialEq, Eq, Encode, Debug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub struct FunctionArgumentMetadata { + pub name: DecodeDifferentStr, + pub ty: DecodeDifferentStr, +} + +/// Metadata about an outer event. +#[derive(Clone, PartialEq, Eq, Encode, Debug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub struct OuterEventMetadata { + pub name: DecodeDifferentStr, + pub events: DecodeDifferentArray< + (&'static str, FnEncode<&'static [EventMetadata]>), + (StringBuf, Vec), + >, +} + +/// Metadata about an event. +#[derive(Clone, PartialEq, Eq, Encode, Debug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub struct EventMetadata { + pub name: DecodeDifferentStr, + pub arguments: DecodeDifferentArray<&'static str, StringBuf>, + pub documentation: DecodeDifferentArray<&'static str, StringBuf>, +} + +/// Metadata about one storage entry. +#[derive(Clone, PartialEq, Eq, Encode, Debug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub struct StorageEntryMetadata { + pub name: DecodeDifferentStr, + pub modifier: StorageEntryModifier, + pub ty: StorageEntryType, + pub default: ByteGetter, + pub documentation: DecodeDifferentArray<&'static str, StringBuf>, } -/// The metadata of a runtime. -// todo: [AJ] add back clone derive if required (requires PortableRegistry to implement clone) -#[derive(PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] -pub struct RuntimeMetadataV13 { - pub types: PortableRegistry, - /// Metadata of all the pallets. - pub pallets: Vec>, - /// Metadata of the extrinsic. - pub extrinsic: ExtrinsicMetadata, +/// Metadata about a module constant. +#[derive(Clone, PartialEq, Eq, Encode, Debug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub struct ModuleConstantMetadata { + pub name: DecodeDifferentStr, + pub ty: DecodeDifferentStr, + pub value: ByteGetter, + pub documentation: DecodeDifferentArray<&'static str, StringBuf>, } -impl RuntimeMetadataV13 { - pub fn new(pallets: Vec, extrinsic: ExtrinsicMetadata) -> Self { - let mut registry = Registry::new(); - let pallets = registry.map_into_portable(pallets); - let extrinsic = extrinsic.into_portable(&mut registry); - Self { - types: registry.into(), - pallets, - extrinsic, - } - } +/// Metadata about a module error. +#[derive(Clone, PartialEq, Eq, Encode, Debug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub struct ErrorMetadata { + pub name: DecodeDifferentStr, + pub documentation: DecodeDifferentArray<&'static str, StringBuf>, } -/// Metadata of the extrinsic used by the runtime. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] -#[cfg_attr( - feature = "std", - serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) -)] -pub struct ExtrinsicMetadata { - /// The type of the extrinsic. - pub ty: T::Type, - /// Extrinsic version. - pub version: u8, - /// The signed extensions in the order they appear in the extrinsic. - pub signed_extensions: Vec>, +/// Metadata about errors in a module. +pub trait ModuleErrorMetadata { + fn metadata() -> &'static [ErrorMetadata]; } -impl IntoPortable for ExtrinsicMetadata { - type Output = ExtrinsicMetadata; - - fn into_portable(self, registry: &mut Registry) -> Self::Output { - ExtrinsicMetadata { - ty: registry.register_type(&self.ty), - version: self.version, - signed_extensions: registry.map_into_portable(self.signed_extensions), - } +impl ModuleErrorMetadata for &'static str { + fn metadata() -> &'static [ErrorMetadata] { + &[] } } -/// Metadata of an extrinsic's signed extension. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] -#[cfg_attr( - feature = "std", - serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) -)] -pub struct SignedExtensionMetadata { - /// The unique signed extension identifier, which may be different from the type name. - pub identifier: T::String, - /// The signed extensions in the order they appear in the extrinsic. - pub ty: T::Type, -} - -impl IntoPortable for SignedExtensionMetadata { - type Output = SignedExtensionMetadata; - - fn into_portable(self, registry: &mut Registry) -> Self::Output { - SignedExtensionMetadata { - identifier: self.identifier.into_portable(registry), - ty: registry.register_type(&self.ty), - } - } +/// A technical trait to store lazy initiated vec value as static dyn pointer. +pub trait DefaultByte: Send + Sync { + fn default_byte(&self) -> Vec; } -/// All metadata about an runtime pallet. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] -#[cfg_attr( - feature = "std", - serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) -)] -pub struct PalletMetadata { - pub name: T::String, - pub storage: Option>, - pub calls: Option>, - pub event: Option>, - pub constants: Vec>, - pub error: Option>, - /// Define the index of the pallet, this index will be used for the encoding of pallet event, - /// call and origin variants. - pub index: u8, -} +/// Wrapper over dyn pointer for accessing a cached once byte value. +#[derive(Clone)] +pub struct DefaultByteGetter(pub &'static dyn DefaultByte); -impl IntoPortable for PalletMetadata { - type Output = PalletMetadata; +/// Decode different for static lazy initiated byte value. +pub type ByteGetter = DecodeDifferent>; - fn into_portable(self, registry: &mut Registry) -> Self::Output { - PalletMetadata { - name: self.name.into_portable(registry), - storage: self.storage.map(|storage| storage.into_portable(registry)), - calls: self.calls.map(|calls| calls.into_portable(registry)), - event: self.event.map(|event| event.into_portable(registry)), - constants: registry.map_into_portable(self.constants), - error: self.error.map(|error| error.into_portable(registry)), - index: self.index, - } +impl Encode for DefaultByteGetter { + fn encode_to(&self, dest: &mut W) { + self.0.default_byte().encode_to(dest) } } -/// All metadata of the pallet's storage. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] -#[cfg_attr( - feature = "std", - serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) -)] -pub struct PalletStorageMetadata { - /// The common prefix used by all storage entries. - pub prefix: T::String, - pub entries: Vec>, -} - -impl IntoPortable for PalletStorageMetadata { - type Output = PalletStorageMetadata; +impl codec::EncodeLike for DefaultByteGetter {} - fn into_portable(self, registry: &mut Registry) -> Self::Output { - PalletStorageMetadata { - prefix: self.prefix.into_portable(registry), - entries: registry.map_into_portable(self.entries), - } +impl PartialEq for DefaultByteGetter { + fn eq(&self, other: &DefaultByteGetter) -> bool { + let left = self.0.default_byte(); + let right = other.0.default_byte(); + left.eq(&right) } } -/// All the metadata about one storage entry. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] -#[cfg_attr( - feature = "std", - serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) -)] -pub struct StorageEntryMetadata { - pub name: T::String, - pub modifier: StorageEntryModifier, - pub ty: StorageEntryType, - pub default: ByteGetter, - pub documentation: Vec, -} - -impl IntoPortable for StorageEntryMetadata { - type Output = StorageEntryMetadata; +impl Eq for DefaultByteGetter {} - fn into_portable(self, registry: &mut Registry) -> Self::Output { - StorageEntryMetadata { - name: self.name.into_portable(registry), - modifier: self.modifier, - ty: self.ty.into_portable(registry), - default: self.default, - documentation: registry.map_into_portable(self.documentation), - } +#[cfg(feature = "std")] +impl serde::Serialize for DefaultByteGetter { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.0.default_byte().serialize(serializer) } } -/// A storage entry modifier. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] -pub enum StorageEntryModifier { - Optional, - Default, +impl core::fmt::Debug for DefaultByteGetter { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + self.0.default_byte().fmt(f) + } } /// Hasher used by storage maps -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] +#[derive(Clone, PartialEq, Eq, Encode, Debug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] pub enum StorageHasher { Blake2_128, Blake2_256, @@ -232,245 +168,82 @@ pub enum StorageHasher { } /// A storage entry type. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] -#[cfg_attr( - feature = "std", - serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) -)] -pub enum StorageEntryType { - Plain(T::Type), +#[derive(Clone, PartialEq, Eq, Encode, Debug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub enum StorageEntryType { + Plain(DecodeDifferentStr), Map { hasher: StorageHasher, - key: T::Type, - value: T::Type, + key: DecodeDifferentStr, + value: DecodeDifferentStr, // is_linked flag previously, unused now to keep backwards compat unused: bool, }, DoubleMap { hasher: StorageHasher, - key1: T::Type, - key2: T::Type, - value: T::Type, + key1: DecodeDifferentStr, + key2: DecodeDifferentStr, + value: DecodeDifferentStr, key2_hasher: StorageHasher, }, + NMap { + keys: DecodeDifferentArray<&'static str, StringBuf>, + hashers: DecodeDifferentArray, + value: DecodeDifferentStr, + }, } -impl IntoPortable for StorageEntryType { - type Output = StorageEntryType; - - fn into_portable(self, registry: &mut Registry) -> Self::Output { - match self { - Self::Plain(plain) => StorageEntryType::Plain(registry.register_type(&plain)), - Self::Map { - hasher, - key, - value, - unused, - } => StorageEntryType::Map { - hasher, - key: registry.register_type(&key), - value: registry.register_type(&value), - unused, - }, - Self::DoubleMap { - hasher, - key1, - key2, - value, - key2_hasher, - } => StorageEntryType::DoubleMap { - hasher, - key1: registry.register_type(&key1), - key2: registry.register_type(&key2), - value: registry.register_type(&value), - key2_hasher, - }, - } - } -} - -/// Metadata for all calls in a pallet -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] -#[cfg_attr( - feature = "std", - serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) -)] -pub struct PalletCallMetadata { - /// The corresponding enum type for the pallet call. - pub ty: T::Type, - pub calls: Vec>, -} - -impl IntoPortable for PalletCallMetadata { - type Output = PalletCallMetadata; - - fn into_portable(self, registry: &mut Registry) -> Self::Output { - PalletCallMetadata { - ty: registry.register_type(&self.ty), - calls: registry.map_into_portable(self.calls), - } - } -} - -/// All the metadata about a function. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] -#[cfg_attr( - feature = "std", - serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) -)] -pub struct FunctionMetadata { - pub name: T::String, - pub arguments: Vec>, - pub documentation: Vec, -} - -impl IntoPortable for FunctionMetadata { - type Output = FunctionMetadata; - - fn into_portable(self, registry: &mut Registry) -> Self::Output { - FunctionMetadata { - name: self.name.into_portable(registry), - arguments: registry.map_into_portable(self.arguments), - documentation: registry.map_into_portable(self.documentation), - } - } -} - -/// All the metadata about a function argument. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] -pub struct FunctionArgumentMetadata { - pub name: T::String, - pub ty: T::Type, -} - -impl IntoPortable for FunctionArgumentMetadata { - type Output = FunctionArgumentMetadata; - - fn into_portable(self, registry: &mut Registry) -> Self::Output { - FunctionArgumentMetadata { - name: self.name.into_portable(registry), - ty: registry.register_type(&self.ty), - } - } -} - -/// Metadata about the pallet event type. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] -pub struct PalletEventMetadata { - pub ty: T::Type, -} - -impl IntoPortable for PalletEventMetadata { - type Output = PalletEventMetadata; - - fn into_portable(self, registry: &mut Registry) -> Self::Output { - PalletEventMetadata { - ty: registry.register_type(&self.ty), - } - } -} - -/// All the metadata about one pallet constant. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] -#[cfg_attr( - feature = "std", - serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) -)] -pub struct PalletConstantMetadata { - pub name: T::String, - pub ty: T::Type, - pub value: ByteGetter, - pub documentation: Vec, -} - -impl IntoPortable for PalletConstantMetadata { - type Output = PalletConstantMetadata; - - fn into_portable(self, registry: &mut Registry) -> Self::Output { - PalletConstantMetadata { - name: self.name.into_portable(registry), - ty: registry.register_type(&self.ty), - value: self.value, - documentation: registry.map_into_portable(self.documentation), - } - } -} - -/// Metadata about a pallet error. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] -#[cfg_attr(feature = "std", serde(bound(serialize = "T::Type: Serialize")))] -pub struct PalletErrorMetadata { - /// The error type information. - pub ty: T::Type, +/// A storage entry modifier. +#[derive(Clone, PartialEq, Eq, Encode, Debug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub enum StorageEntryModifier { + Optional, + Default, } -impl IntoPortable for PalletErrorMetadata { - type Output = PalletErrorMetadata; - - fn into_portable(self, registry: &mut Registry) -> Self::Output { - PalletErrorMetadata { - ty: registry.register_type(&self.ty), - } - } +/// All metadata of the storage. +#[derive(Clone, PartialEq, Eq, Encode, Debug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub struct StorageMetadata { + /// The common prefix used by all storage entries. + pub prefix: DecodeDifferent<&'static str, StringBuf>, + pub entries: DecodeDifferent<&'static [StorageEntryMetadata], Vec>, } -/// A type specification. -/// -/// This contains the actual type as well as an optional compile-time -/// known displayed representation of the type. This is useful for cases -/// where the type is used through a type alias in order to provide -/// information about the alias name. -/// -/// # Examples -/// -/// Consider the following Rust function: -/// ```no_compile -/// fn is_sorted(input: &[i32], pred: Predicate) -> bool; -/// ``` -/// In this above example `input` would have no displayable name, -/// `pred`'s display name is `Predicate` and the display name of -/// the return type is simply `bool`. Note that `Predicate` could -/// simply be a type alias to `fn(i32, i32) -> Ordering`. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] -#[cfg_attr( - feature = "std", - serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) -)] -pub struct TypeSpec { - /// The actual type. - pub ty: T::Type, - /// The compile-time known displayed representation of the type. - pub name: T::String, +/// Metadata of the extrinsic used by the runtime. +#[derive(Eq, Encode, PartialEq, Debug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub struct ExtrinsicMetadata { + /// Extrinsic version. + pub version: u8, + /// The signed extensions in the order they appear in the extrinsic. + pub signed_extensions: Vec, } -impl IntoPortable for TypeSpec { - type Output = TypeSpec; - - fn into_portable(self, registry: &mut Registry) -> Self::Output { - TypeSpec { - ty: registry.register_type(&self.ty), - name: self.name.into_portable(registry), - } - } +/// The metadata of a runtime. +#[derive(Eq, Encode, PartialEq, Debug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub struct RuntimeMetadataV13 { + /// Metadata of all the modules. + pub modules: DecodeDifferentArray, + /// Metadata of the extrinsic. + pub extrinsic: ExtrinsicMetadata, +} + +/// All metadata about an runtime module. +#[derive(Clone, PartialEq, Eq, Encode, Debug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub struct ModuleMetadata { + pub name: DecodeDifferentStr, + pub storage: Option, StorageMetadata>>, + pub calls: ODFnA, + pub event: ODFnA, + pub constants: DFnA, + pub errors: DFnA, + /// Define the index of the module, this index will be used for the encoding of module event, + /// call and origin variants. + pub index: u8, } -impl TypeSpec { - /// Creates a new type specification without a display name. - pub fn new(name: &'static str) -> Self - where - T: TypeInfo + 'static, - { - Self { - ty: meta_type::(), - name, - } - } -} +type ODFnA = Option>; +type DFnA = DecodeDifferent, Vec>; diff --git a/frame-metadata/src/v14.rs b/frame-metadata/src/v14.rs new file mode 100644 index 0000000..72cf250 --- /dev/null +++ b/frame-metadata/src/v14.rs @@ -0,0 +1,490 @@ +// This file is part of Substrate. + +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +cfg_if::cfg_if! { + if #[cfg(feature = "std")] { + use codec::Decode; + use serde::Serialize; + } +} + +use super::RuntimeMetadataPrefixed; +use codec::Encode; +use scale_info::prelude::vec::Vec; +use scale_info::{ + form::{Form, MetaForm, PortableForm}, + meta_type, IntoPortable, PortableRegistry, Registry, TypeInfo, +}; + +/// Current prefix of metadata +pub const META_RESERVED: u32 = 0x6174656d; // 'meta' warn endianness + +/// Type alias placeholder for `ByteGetter` equivalent. todo: [AJ] figure out what to do here +pub type ByteGetter = Vec; + +pub type RuntimeMetadataLastVersion = RuntimeMetadataV14; + +impl From for super::RuntimeMetadataPrefixed { + fn from(metadata: RuntimeMetadataLastVersion) -> RuntimeMetadataPrefixed { + RuntimeMetadataPrefixed(META_RESERVED, super::RuntimeMetadata::V14(metadata)) + } +} + +/// The metadata of a runtime. +// todo: [AJ] add back clone derive if required (requires PortableRegistry to implement clone) +#[derive(PartialEq, Eq, Encode)] +#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] +pub struct RuntimeMetadataV14 { + pub types: PortableRegistry, + /// Metadata of all the pallets. + pub pallets: Vec>, + /// Metadata of the extrinsic. + pub extrinsic: ExtrinsicMetadata, +} + +impl RuntimeMetadataV14 { + pub fn new(pallets: Vec, extrinsic: ExtrinsicMetadata) -> Self { + let mut registry = Registry::new(); + let pallets = registry.map_into_portable(pallets); + let extrinsic = extrinsic.into_portable(&mut registry); + Self { + types: registry.into(), + pallets, + extrinsic, + } + } +} + +/// Metadata of the extrinsic used by the runtime. +#[derive(Clone, PartialEq, Eq, Encode)] +#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] +#[cfg_attr( + feature = "std", + serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) +)] +pub struct ExtrinsicMetadata { + /// The type of the extrinsic. + pub ty: T::Type, + /// Extrinsic version. + pub version: u8, + /// The signed extensions in the order they appear in the extrinsic. + pub signed_extensions: Vec>, +} + +impl IntoPortable for ExtrinsicMetadata { + type Output = ExtrinsicMetadata; + + fn into_portable(self, registry: &mut Registry) -> Self::Output { + ExtrinsicMetadata { + ty: registry.register_type(&self.ty), + version: self.version, + signed_extensions: registry.map_into_portable(self.signed_extensions), + } + } +} + +/// Metadata of an extrinsic's signed extension. +#[derive(Clone, PartialEq, Eq, Encode)] +#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] +#[cfg_attr( + feature = "std", + serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) +)] +pub struct SignedExtensionMetadata { + /// The unique signed extension identifier, which may be different from the type name. + pub identifier: T::String, + /// The signed extensions in the order they appear in the extrinsic. + pub ty: T::Type, +} + +impl IntoPortable for SignedExtensionMetadata { + type Output = SignedExtensionMetadata; + + fn into_portable(self, registry: &mut Registry) -> Self::Output { + SignedExtensionMetadata { + identifier: self.identifier.into_portable(registry), + ty: registry.register_type(&self.ty), + } + } +} + +/// All metadata about an runtime pallet. +#[derive(Clone, PartialEq, Eq, Encode)] +#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] +#[cfg_attr( + feature = "std", + serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) +)] +pub struct PalletMetadata { + pub name: T::String, + pub storage: Option>, + pub calls: Option>, + pub event: Option>, + pub constants: Vec>, + pub error: Option>, + /// Define the index of the pallet, this index will be used for the encoding of pallet event, + /// call and origin variants. + pub index: u8, +} + +impl IntoPortable for PalletMetadata { + type Output = PalletMetadata; + + fn into_portable(self, registry: &mut Registry) -> Self::Output { + PalletMetadata { + name: self.name.into_portable(registry), + storage: self.storage.map(|storage| storage.into_portable(registry)), + calls: self.calls.map(|calls| calls.into_portable(registry)), + event: self.event.map(|event| event.into_portable(registry)), + constants: registry.map_into_portable(self.constants), + error: self.error.map(|error| error.into_portable(registry)), + index: self.index, + } + } +} + +/// All metadata of the pallet's storage. +#[derive(Clone, PartialEq, Eq, Encode)] +#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] +#[cfg_attr( + feature = "std", + serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) +)] +pub struct PalletStorageMetadata { + /// The common prefix used by all storage entries. + pub prefix: T::String, + pub entries: Vec>, +} + +impl IntoPortable for PalletStorageMetadata { + type Output = PalletStorageMetadata; + + fn into_portable(self, registry: &mut Registry) -> Self::Output { + PalletStorageMetadata { + prefix: self.prefix.into_portable(registry), + entries: registry.map_into_portable(self.entries), + } + } +} + +/// Metadata about one storage entry. +#[derive(Clone, PartialEq, Eq, Encode)] +#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] +#[cfg_attr( + feature = "std", + serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) +)] +pub struct StorageEntryMetadata { + pub name: T::String, + pub modifier: StorageEntryModifier, + pub ty: StorageEntryType, + pub default: ByteGetter, + pub documentation: Vec, +} + +impl IntoPortable for StorageEntryMetadata { + type Output = StorageEntryMetadata; + + fn into_portable(self, registry: &mut Registry) -> Self::Output { + StorageEntryMetadata { + name: self.name.into_portable(registry), + modifier: self.modifier, + ty: self.ty.into_portable(registry), + default: self.default, + documentation: registry.map_into_portable(self.documentation), + } + } +} + +/// A storage entry modifier. +#[derive(Clone, PartialEq, Eq, Encode)] +#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] +pub enum StorageEntryModifier { + Optional, + Default, +} + +/// Hasher used by storage maps +#[derive(Clone, PartialEq, Eq, Encode)] +#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] +pub enum StorageHasher { + Blake2_128, + Blake2_256, + Blake2_128Concat, + Twox128, + Twox256, + Twox64Concat, + Identity, +} + +/// A storage entry type. +#[derive(Clone, PartialEq, Eq, Encode)] +#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] +#[cfg_attr( + feature = "std", + serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) +)] +pub enum StorageEntryType { + Plain(T::Type), + Map { + hasher: StorageHasher, + key: T::Type, + value: T::Type, + // is_linked flag previously, unused now to keep backwards compat + unused: bool, + }, + DoubleMap { + hasher: StorageHasher, + key1: T::Type, + key2: T::Type, + value: T::Type, + key2_hasher: StorageHasher, + }, + NMap { + keys: T::Type, + hashers: Vec, + value: T::Type, + }, +} + +impl IntoPortable for StorageEntryType { + type Output = StorageEntryType; + + fn into_portable(self, registry: &mut Registry) -> Self::Output { + match self { + Self::Plain(plain) => StorageEntryType::Plain(registry.register_type(&plain)), + Self::Map { + hasher, + key, + value, + unused, + } => StorageEntryType::Map { + hasher, + key: registry.register_type(&key), + value: registry.register_type(&value), + unused, + }, + Self::DoubleMap { + hasher, + key1, + key2, + value, + key2_hasher, + } => StorageEntryType::DoubleMap { + hasher, + key1: registry.register_type(&key1), + key2: registry.register_type(&key2), + value: registry.register_type(&value), + key2_hasher, + }, + StorageEntryType::NMap { + keys, + hashers, + value, + } => StorageEntryType::NMap { + keys: registry.register_type(&keys), + hashers, + value: registry.register_type(&value), + }, + } + } +} + +/// Metadata for all calls in a pallet +#[derive(Clone, PartialEq, Eq, Encode)] +#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] +#[cfg_attr( + feature = "std", + serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) +)] +pub struct PalletCallMetadata { + /// The corresponding enum type for the pallet call. + pub ty: T::Type, + pub calls: Vec>, +} + +impl IntoPortable for PalletCallMetadata { + type Output = PalletCallMetadata; + + fn into_portable(self, registry: &mut Registry) -> Self::Output { + PalletCallMetadata { + ty: registry.register_type(&self.ty), + calls: registry.map_into_portable(self.calls), + } + } +} + +/// Metadata about a function. +#[derive(Clone, PartialEq, Eq, Encode)] +#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] +#[cfg_attr( + feature = "std", + serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) +)] +pub struct FunctionMetadata { + pub name: T::String, + pub arguments: Vec>, + pub documentation: Vec, +} + +impl IntoPortable for FunctionMetadata { + type Output = FunctionMetadata; + + fn into_portable(self, registry: &mut Registry) -> Self::Output { + FunctionMetadata { + name: self.name.into_portable(registry), + arguments: registry.map_into_portable(self.arguments), + documentation: registry.map_into_portable(self.documentation), + } + } +} + +/// Metadata about a function argument. +#[derive(Clone, PartialEq, Eq, Encode)] +#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] +pub struct FunctionArgumentMetadata { + pub name: T::String, + pub ty: T::Type, +} + +impl IntoPortable for FunctionArgumentMetadata { + type Output = FunctionArgumentMetadata; + + fn into_portable(self, registry: &mut Registry) -> Self::Output { + FunctionArgumentMetadata { + name: self.name.into_portable(registry), + ty: registry.register_type(&self.ty), + } + } +} + +/// Metadata about the pallet event type. +#[derive(Clone, PartialEq, Eq, Encode)] +#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] +pub struct PalletEventMetadata { + pub ty: T::Type, +} + +impl IntoPortable for PalletEventMetadata { + type Output = PalletEventMetadata; + + fn into_portable(self, registry: &mut Registry) -> Self::Output { + PalletEventMetadata { + ty: registry.register_type(&self.ty), + } + } +} + +/// Metadata about one pallet constant. +#[derive(Clone, PartialEq, Eq, Encode)] +#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] +#[cfg_attr( + feature = "std", + serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) +)] +pub struct PalletConstantMetadata { + pub name: T::String, + pub ty: T::Type, + pub value: ByteGetter, + pub documentation: Vec, +} + +impl IntoPortable for PalletConstantMetadata { + type Output = PalletConstantMetadata; + + fn into_portable(self, registry: &mut Registry) -> Self::Output { + PalletConstantMetadata { + name: self.name.into_portable(registry), + ty: registry.register_type(&self.ty), + value: self.value, + documentation: registry.map_into_portable(self.documentation), + } + } +} + +/// Metadata about a pallet error. +#[derive(Clone, PartialEq, Eq, Encode)] +#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] +#[cfg_attr(feature = "std", serde(bound(serialize = "T::Type: Serialize")))] +pub struct PalletErrorMetadata { + /// The error type information. + pub ty: T::Type, +} + +impl IntoPortable for PalletErrorMetadata { + type Output = PalletErrorMetadata; + + fn into_portable(self, registry: &mut Registry) -> Self::Output { + PalletErrorMetadata { + ty: registry.register_type(&self.ty), + } + } +} + +/// A type specification. +/// +/// This contains the actual type as well as an optional compile-time +/// known displayed representation of the type. This is useful for cases +/// where the type is used through a type alias in order to provide +/// information about the alias name. +/// +/// # Examples +/// +/// Consider the following Rust function: +/// ```no_compile +/// fn is_sorted(input: &[i32], pred: Predicate) -> bool; +/// ``` +/// In this above example `input` would have no displayable name, +/// `pred`'s display name is `Predicate` and the display name of +/// the return type is simply `bool`. Note that `Predicate` could +/// simply be a type alias to `fn(i32, i32) -> Ordering`. +#[derive(Clone, PartialEq, Eq, Encode)] +#[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))] +#[cfg_attr( + feature = "std", + serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) +)] +pub struct TypeSpec { + /// The actual type. + pub ty: T::Type, + /// The compile-time known displayed representation of the type. + pub name: T::String, +} + +impl IntoPortable for TypeSpec { + type Output = TypeSpec; + + fn into_portable(self, registry: &mut Registry) -> Self::Output { + TypeSpec { + ty: registry.register_type(&self.ty), + name: self.name.into_portable(registry), + } + } +} + +impl TypeSpec { + /// Creates a new type specification with a display name. + pub fn new(name: &'static str) -> Self + where + T: TypeInfo + 'static, + { + Self { + ty: meta_type::(), + name, + } + } +}