use crate::prelude::{vec, vec::Vec};
use crate::{
build::TypeBuilder,
form::{Form, MetaForm, PortableForm},
IntoPortable, MetaType, Registry, TypeInfo,
};
use derive_more::From;
use scale::Encode;
#[cfg(feature = "serde")]
use serde::{de::DeserializeOwned, Deserialize, Serialize};
mod composite;
mod fields;
mod path;
mod variant;
pub use self::{composite::*, fields::*, path::*, variant::*};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "serde",
serde(bound(
serialize = "T::Type: Serialize, T::String: Serialize",
deserialize = "T::Type: DeserializeOwned, T::String: DeserializeOwned",
))
)]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, From, Debug, Encode)]
pub struct Type<T: Form = MetaForm> {
#[cfg_attr(
feature = "serde",
serde(skip_serializing_if = "Path::is_empty", default)
)]
pub path: Path<T>,
#[cfg_attr(
feature = "serde",
serde(rename = "params", skip_serializing_if = "Vec::is_empty", default)
)]
pub type_params: Vec<TypeParameter<T>>,
#[cfg_attr(feature = "serde", serde(rename = "def"))]
pub type_def: TypeDef<T>,
#[cfg_attr(
feature = "serde",
serde(skip_serializing_if = "Vec::is_empty", default)
)]
pub docs: Vec<T::String>,
}
impl IntoPortable for Type {
type Output = Type<PortableForm>;
fn into_portable(self, registry: &mut Registry) -> Self::Output {
Type {
path: self.path.into_portable(registry),
type_params: registry.map_into_portable(self.type_params),
type_def: self.type_def.into_portable(registry),
docs: self.docs.into_iter().map(Into::into).collect(),
}
}
}
macro_rules! impl_from_type_def_for_type {
( $( $t:ty ), + $(,)?) => { $(
impl<F: Form> From<$t> for Type<F> {
fn from(item: $t) -> Self {
Self::new(Path::voldemort(), Vec::new(), item, Vec::new())
}
}
)* }
}
impl_from_type_def_for_type!(
TypeDefPrimitive,
TypeDefArray<F>,
TypeDefSequence<F>,
TypeDefTuple<F>,
TypeDefCompact<F>,
TypeDefBitSequence<F>,
);
impl Type {
pub fn builder() -> TypeBuilder {
TypeBuilder::default()
}
pub fn builder_portable() -> TypeBuilder<PortableForm> {
TypeBuilder::default()
}
}
impl<F> Type<F>
where
F: Form,
{
pub fn new<I, D>(path: Path<F>, type_params: I, type_def: D, docs: Vec<F::String>) -> Type<F>
where
I: IntoIterator<Item = TypeParameter<F>>,
D: Into<TypeDef<F>>,
{
Self {
path,
type_params: type_params.into_iter().collect(),
type_def: type_def.into(),
docs,
}
}
}
impl<T> Type<T>
where
T: Form,
{
#[deprecated(
since = "2.5.0",
note = "Prefer to access the fields directly; this getter will be removed in the next major version"
)]
pub fn path(&self) -> &Path<T> {
&self.path
}
#[deprecated(
since = "2.5.0",
note = "Prefer to access the fields directly; this getter will be removed in the next major version"
)]
pub fn type_params(&self) -> &[TypeParameter<T>] {
&self.type_params
}
#[deprecated(
since = "2.5.0",
note = "Prefer to access the fields directly; this getter will be removed in the next major version"
)]
pub fn type_def(&self) -> &TypeDef<T> {
&self.type_def
}
#[deprecated(
since = "2.5.0",
note = "Prefer to access the fields directly; this getter will be removed in the next major version"
)]
pub fn docs(&self) -> &[T::String] {
&self.docs
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "serde",
serde(bound(
serialize = "T::Type: Serialize, T::String: Serialize",
deserialize = "T::Type: DeserializeOwned, T::String: DeserializeOwned",
))
)]
#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, From, Debug, Encode)]
pub struct TypeParameter<T: Form = MetaForm> {
pub name: T::String,
#[cfg_attr(feature = "serde", serde(rename = "type"))]
pub ty: Option<T::Type>,
}
impl IntoPortable for TypeParameter {
type Output = TypeParameter<PortableForm>;
fn into_portable(self, registry: &mut Registry) -> Self::Output {
TypeParameter {
name: self.name.into(),
ty: self.ty.map(|ty| registry.register_type(&ty)),
}
}
}
impl TypeParameter<MetaForm> {
pub fn new(name: <MetaForm as Form>::String, ty: Option<<MetaForm as Form>::Type>) -> Self {
Self { name, ty }
}
}
impl TypeParameter<PortableForm> {
pub fn new_portable(
name: <PortableForm as Form>::String,
ty: Option<<PortableForm as Form>::Type>,
) -> Self {
Self { name, ty }
}
}
impl<T> TypeParameter<T>
where
T: Form,
{
#[deprecated(
since = "2.5.0",
note = "Prefer to access the fields directly; this getter will be removed in the next major version"
)]
pub fn ty(&self) -> Option<&T::Type> {
self.ty.as_ref()
}
#[deprecated(
since = "2.5.0",
note = "Prefer to access the fields directly; this getter will be removed in the next major version"
)]
pub fn name(&self) -> &T::String {
&self.name
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "serde",
serde(bound(
serialize = "T::Type: Serialize, T::String: Serialize",
deserialize = "T::Type: DeserializeOwned, T::String: DeserializeOwned",
))
)]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, Encode)]
pub enum TypeDef<T: Form = MetaForm> {
#[codec(index = 0)]
Composite(TypeDefComposite<T>),
#[codec(index = 1)]
Variant(TypeDefVariant<T>),
#[codec(index = 2)]
Sequence(TypeDefSequence<T>),
#[codec(index = 3)]
Array(TypeDefArray<T>),
#[codec(index = 4)]
Tuple(TypeDefTuple<T>),
#[codec(index = 5)]
Primitive(TypeDefPrimitive),
#[codec(index = 6)]
Compact(TypeDefCompact<T>),
#[codec(index = 7)]
BitSequence(TypeDefBitSequence<T>),
}
macro_rules! impl_from_type_defs {
( $($from:ty => $variant:ident, )* ) => { $(
impl<F: Form> From<$from> for TypeDef<F> {
fn from(x: $from) -> Self {
Self::$variant(x)
}
}
)* }
}
impl_from_type_defs!(
TypeDefComposite<F> => Composite,
TypeDefVariant<F> => Variant,
TypeDefSequence<F> => Sequence,
TypeDefArray<F> => Array,
TypeDefTuple<F> => Tuple,
TypeDefPrimitive => Primitive,
TypeDefCompact<F> => Compact,
TypeDefBitSequence<F> => BitSequence,
);
impl IntoPortable for TypeDef {
type Output = TypeDef<PortableForm>;
fn into_portable(self, registry: &mut Registry) -> Self::Output {
match self {
TypeDef::Composite(composite) => composite.into_portable(registry).into(),
TypeDef::Variant(variant) => variant.into_portable(registry).into(),
TypeDef::Sequence(sequence) => sequence.into_portable(registry).into(),
TypeDef::Array(array) => array.into_portable(registry).into(),
TypeDef::Tuple(tuple) => tuple.into_portable(registry).into(),
TypeDef::Primitive(primitive) => primitive.into(),
TypeDef::Compact(compact) => compact.into_portable(registry).into(),
TypeDef::BitSequence(bitseq) => bitseq.into_portable(registry).into(),
}
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)]
pub enum TypeDefPrimitive {
#[codec(index = 0)]
Bool,
#[codec(index = 1)]
Char,
#[codec(index = 2)]
Str,
#[codec(index = 3)]
U8,
#[codec(index = 4)]
U16,
#[codec(index = 5)]
U32,
#[codec(index = 6)]
U64,
#[codec(index = 7)]
U128,
#[codec(index = 8)]
U256,
#[codec(index = 9)]
I8,
#[codec(index = 10)]
I16,
#[codec(index = 11)]
I32,
#[codec(index = 12)]
I64,
#[codec(index = 13)]
I128,
#[codec(index = 14)]
I256,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)]
pub struct TypeDefArray<T: Form = MetaForm> {
pub len: u32,
#[cfg_attr(feature = "serde", serde(rename = "type"))]
pub type_param: T::Type,
}
impl IntoPortable for TypeDefArray {
type Output = TypeDefArray<PortableForm>;
fn into_portable(self, registry: &mut Registry) -> Self::Output {
TypeDefArray {
len: self.len,
type_param: registry.register_type(&self.type_param),
}
}
}
#[allow(clippy::len_without_is_empty)]
impl<T> TypeDefArray<T>
where
T: Form,
{
pub fn new(len: u32, type_param: <T as Form>::Type) -> Self {
Self { len, type_param }
}
#[deprecated(
since = "2.5.0",
note = "Prefer to access the fields directly; this getter will be removed in the next major version"
)]
pub fn len(&self) -> u32 {
self.len
}
#[deprecated(
since = "2.5.0",
note = "Prefer to access the fields directly; this getter will be removed in the next major version"
)]
pub fn type_param(&self) -> &T::Type {
&self.type_param
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "serde",
serde(bound(
serialize = "T::Type: Serialize, T::String: Serialize",
deserialize = "T::Type: DeserializeOwned, T::String: DeserializeOwned",
))
)]
#[cfg_attr(feature = "serde", serde(transparent))]
#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)]
pub struct TypeDefTuple<T: Form = MetaForm> {
pub fields: Vec<T::Type>,
}
impl IntoPortable for TypeDefTuple {
type Output = TypeDefTuple<PortableForm>;
fn into_portable(self, registry: &mut Registry) -> Self::Output {
TypeDefTuple {
fields: registry.register_types(self.fields),
}
}
}
impl TypeDefTuple {
pub fn new<T>(type_params: T) -> Self
where
T: IntoIterator<Item = MetaType>,
{
Self {
fields: type_params
.into_iter()
.filter(|ty| !ty.is_phantom())
.collect(),
}
}
pub fn unit() -> Self {
Self::new(vec![])
}
}
impl TypeDefTuple<PortableForm> {
pub fn new_portable<I>(type_params: I) -> Self
where
I: IntoIterator<Item = <PortableForm as Form>::Type>,
{
Self {
fields: type_params.into_iter().collect(),
}
}
}
impl<T> TypeDefTuple<T>
where
T: Form,
{
#[deprecated(
since = "2.5.0",
note = "Prefer to access the fields directly; this getter will be removed in the next major version"
)]
pub fn fields(&self) -> &[T::Type] {
&self.fields
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)]
pub struct TypeDefSequence<T: Form = MetaForm> {
#[cfg_attr(feature = "serde", serde(rename = "type"))]
pub type_param: T::Type,
}
impl IntoPortable for TypeDefSequence {
type Output = TypeDefSequence<PortableForm>;
fn into_portable(self, registry: &mut Registry) -> Self::Output {
TypeDefSequence {
type_param: registry.register_type(&self.type_param),
}
}
}
impl TypeDefSequence {
pub fn of<T>() -> Self
where
T: TypeInfo + 'static,
{
Self::new(MetaType::new::<T>())
}
}
impl<T> TypeDefSequence<T>
where
T: Form,
{
pub fn new(type_param: <T as Form>::Type) -> Self {
Self { type_param }
}
#[deprecated(
since = "2.5.0",
note = "Prefer to access the fields directly; this getter will be removed in the next major version"
)]
pub fn type_param(&self) -> &T::Type {
&self.type_param
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)]
pub struct TypeDefCompact<T: Form = MetaForm> {
#[cfg_attr(feature = "serde", serde(rename = "type"))]
pub type_param: T::Type,
}
impl IntoPortable for TypeDefCompact {
type Output = TypeDefCompact<PortableForm>;
fn into_portable(self, registry: &mut Registry) -> Self::Output {
TypeDefCompact {
type_param: registry.register_type(&self.type_param),
}
}
}
impl<T> TypeDefCompact<T>
where
T: Form,
{
pub fn new(type_param: <T as Form>::Type) -> Self {
Self { type_param }
}
#[deprecated(
since = "2.5.0",
note = "Prefer to access the fields directly; this getter will be removed in the next major version"
)]
pub fn type_param(&self) -> &T::Type {
&self.type_param
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)]
pub struct TypeDefBitSequence<T: Form = MetaForm> {
pub bit_store_type: T::Type,
pub bit_order_type: T::Type,
}
impl IntoPortable for TypeDefBitSequence {
type Output = TypeDefBitSequence<PortableForm>;
fn into_portable(self, registry: &mut Registry) -> Self::Output {
TypeDefBitSequence {
bit_store_type: registry.register_type(&self.bit_store_type),
bit_order_type: registry.register_type(&self.bit_order_type),
}
}
}
impl<T> TypeDefBitSequence<T>
where
T: Form,
{
#[deprecated(
since = "2.5.0",
note = "Prefer to access the fields directly; this getter will be removed in the next major version"
)]
pub fn bit_order_type(&self) -> &T::Type {
&self.bit_order_type
}
#[deprecated(
since = "2.5.0",
note = "Prefer to access the fields directly; this getter will be removed in the next major version"
)]
pub fn bit_store_type(&self) -> &T::Type {
&self.bit_store_type
}
}
impl TypeDefBitSequence {
pub fn new<Store, Order>() -> Self
where
Store: TypeInfo + 'static,
Order: TypeInfo + 'static,
{
Self {
bit_store_type: MetaType::new::<Store>(),
bit_order_type: MetaType::new::<Order>(),
}
}
}
impl TypeDefBitSequence<PortableForm> {
pub fn new_portable(
bit_store_type: <PortableForm as Form>::Type,
bit_order_type: <PortableForm as Form>::Type,
) -> Self {
Self {
bit_store_type,
bit_order_type,
}
}
}