,
- types_mod_ident: &syn::Ident,
-) -> TokenStream2 {
- let struct_defs =
- super::generate_structs_from_variants(type_gen, event.ty.id(), "Event");
- let event_structs = struct_defs.iter().map(|struct_def| {
- let pallet_name = &pallet.name;
- let event_struct = &struct_def.name;
- let event_name = struct_def.name.to_string();
-
- quote! {
- #struct_def
-
- impl ::subxt::Event for #event_struct {
- const PALLET: &'static str = #pallet_name;
- const EVENT: &'static str = #event_name;
- }
- }
- });
- let event_type = type_gen.resolve_type_path(event.ty.id(), &[]);
-
- quote! {
- pub type Event = #event_type;
- pub mod events {
- use super::#types_mod_ident;
- #( #event_structs )*
- }
- }
-}
diff --git a/codegen/src/api/mod.rs b/codegen/src/api/mod.rs
deleted file mode 100644
index bc46d02745..0000000000
--- a/codegen/src/api/mod.rs
+++ /dev/null
@@ -1,347 +0,0 @@
-// Copyright 2019-2021 Parity Technologies (UK) Ltd.
-// This file is part of subxt.
-//
-// subxt is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// subxt is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with subxt. If not, see .
-
-mod calls;
-mod events;
-mod storage;
-
-use super::GeneratedTypeDerives;
-use crate::{
- ir,
- struct_def::StructDef,
- types::TypeGenerator,
-};
-use codec::Decode;
-use frame_metadata::{
- v14::RuntimeMetadataV14,
- RuntimeMetadata,
- RuntimeMetadataPrefixed,
-};
-use heck::SnakeCase as _;
-use proc_macro2::TokenStream as TokenStream2;
-use proc_macro_error::abort_call_site;
-use quote::{
- format_ident,
- quote,
-};
-use std::{
- collections::HashMap,
- fs,
- io::Read,
- path,
- string::ToString,
-};
-use syn::{
- parse_quote,
- punctuated::Punctuated,
-};
-
-pub fn generate_runtime_api(
- item_mod: syn::ItemMod,
- path: P,
- generated_type_derives: Option>,
-) -> TokenStream2
-where
- P: AsRef,
-{
- let mut file = fs::File::open(&path).unwrap_or_else(|e| {
- abort_call_site!("Failed to open {}: {}", path.as_ref().to_string_lossy(), e)
- });
-
- let mut bytes = Vec::new();
- file.read_to_end(&mut bytes)
- .unwrap_or_else(|e| abort_call_site!("Failed to read metadata file: {}", e));
-
- let metadata = frame_metadata::RuntimeMetadataPrefixed::decode(&mut &bytes[..])
- .unwrap_or_else(|e| abort_call_site!("Failed to decode metadata: {}", e));
-
- let mut derives = GeneratedTypeDerives::default();
- if let Some(user_derives) = generated_type_derives {
- derives.append(user_derives.iter().cloned())
- }
-
- let generator = RuntimeGenerator::new(metadata);
- generator.generate_runtime(item_mod, derives)
-}
-
-pub struct RuntimeGenerator {
- metadata: RuntimeMetadataV14,
-}
-
-impl RuntimeGenerator {
- pub fn new(metadata: RuntimeMetadataPrefixed) -> Self {
- match metadata.1 {
- RuntimeMetadata::V14(v14) => Self { metadata: v14 },
- _ => panic!("Unsupported metadata version {:?}", metadata.1),
- }
- }
-
- pub fn generate_runtime(
- &self,
- item_mod: syn::ItemMod,
- derives: GeneratedTypeDerives,
- ) -> TokenStream2 {
- let item_mod_ir = ir::ItemMod::from(item_mod);
-
- // some hardcoded default type substitutes, can be overridden by user
- let mut type_substitutes = [
- (
- "bitvec::order::Lsb0",
- parse_quote!(::subxt::bitvec::order::Lsb0),
- ),
- (
- "bitvec::order::Msb0",
- parse_quote!(::subxt::bitvec::order::Msb0),
- ),
- (
- "sp_core::crypto::AccountId32",
- parse_quote!(::subxt::sp_core::crypto::AccountId32),
- ),
- (
- "primitive_types::H256",
- parse_quote!(::subxt::sp_core::H256),
- ),
- (
- "sp_runtime::multiaddress::MultiAddress",
- parse_quote!(::subxt::sp_runtime::MultiAddress),
- ),
- (
- "frame_support::traits::misc::WrapperKeepOpaque",
- parse_quote!(::subxt::WrapperKeepOpaque),
- ),
- ]
- .iter()
- .map(|(path, substitute): &(&str, syn::TypePath)| {
- (path.to_string(), substitute.clone())
- })
- .collect::>();
-
- for (path, substitute) in item_mod_ir.type_substitutes().iter() {
- type_substitutes.insert(path.to_string(), substitute.clone());
- }
-
- let type_gen = TypeGenerator::new(
- &self.metadata.types,
- "runtime_types",
- type_substitutes,
- derives.clone(),
- );
- let types_mod = type_gen.generate_types_mod();
- let types_mod_ident = types_mod.ident();
- let pallets_with_mod_names = self
- .metadata
- .pallets
- .iter()
- .map(|pallet| {
- (
- pallet,
- format_ident!("{}", pallet.name.to_string().to_snake_case()),
- )
- })
- .collect::>();
- let modules = pallets_with_mod_names.iter().map(|(pallet, mod_name)| {
- let calls = if let Some(ref calls) = pallet.calls {
- calls::generate_calls(&type_gen, pallet, calls, types_mod_ident)
- } else {
- quote!()
- };
-
- let event = if let Some(ref event) = pallet.event {
- events::generate_events(&type_gen, pallet, event, types_mod_ident)
- } else {
- quote!()
- };
-
- let storage_mod = if let Some(ref storage) = pallet.storage {
- storage::generate_storage(&type_gen, pallet, storage, types_mod_ident)
- } else {
- quote!()
- };
-
- quote! {
- pub mod #mod_name {
- use super::#types_mod_ident;
- #calls
- #event
- #storage_mod
- }
- }
- });
-
- let outer_event_variants = self.metadata.pallets.iter().filter_map(|p| {
- let variant_name = format_ident!("{}", p.name);
- let mod_name = format_ident!("{}", p.name.to_string().to_snake_case());
- let index = proc_macro2::Literal::u8_unsuffixed(p.index);
-
- p.event.as_ref().map(|_| {
- quote! {
- #[codec(index = #index)]
- #variant_name(#mod_name::Event),
- }
- })
- });
-
- let outer_event = quote! {
- #derives
- pub enum Event {
- #( #outer_event_variants )*
- }
- };
-
- let mod_ident = item_mod_ir.ident;
- let pallets_with_storage =
- pallets_with_mod_names
- .iter()
- .filter_map(|(pallet, pallet_mod_name)| {
- pallet.storage.as_ref().map(|_| pallet_mod_name)
- });
- let pallets_with_calls =
- pallets_with_mod_names
- .iter()
- .filter_map(|(pallet, pallet_mod_name)| {
- pallet.calls.as_ref().map(|_| pallet_mod_name)
- });
-
- quote! {
- #[allow(dead_code, unused_imports, non_camel_case_types)]
- pub mod #mod_ident {
- #outer_event
- #( #modules )*
- #types_mod
-
- /// Default configuration of common types for a target Substrate runtime.
- #[derive(Clone, Debug, Default, Eq, PartialEq)]
- pub struct DefaultConfig;
-
- impl ::subxt::Config for DefaultConfig {
- type Index = u32;
- type BlockNumber = u32;
- type Hash = ::subxt::sp_core::H256;
- type Hashing = ::subxt::sp_runtime::traits::BlakeTwo256;
- type AccountId = ::subxt::sp_runtime::AccountId32;
- type Address = ::subxt::sp_runtime::MultiAddress;
- type Header = ::subxt::sp_runtime::generic::Header<
- Self::BlockNumber, ::subxt::sp_runtime::traits::BlakeTwo256
- >;
- type Signature = ::subxt::sp_runtime::MultiSignature;
- type Extrinsic = ::subxt::sp_runtime::OpaqueExtrinsic;
- }
-
- impl ::subxt::ExtrinsicExtraData for DefaultConfig {
- type AccountData = AccountData;
- type Extra = ::subxt::DefaultExtra;
- }
-
- pub type AccountData = self::system::storage::Account;
-
- impl ::subxt::AccountData for AccountData {
- fn nonce(result: &::Value) -> ::Index {
- result.nonce
- }
- fn storage_entry(account_id: ::AccountId) -> Self {
- Self(account_id)
- }
- }
-
- pub struct RuntimeApi> {
- pub client: ::subxt::Client,
- }
-
- impl ::core::convert::From<::subxt::Client> for RuntimeApi
- where
- T: ::subxt::Config + ::subxt::ExtrinsicExtraData,
- {
- fn from(client: ::subxt::Client) -> Self {
- Self { client }
- }
- }
-
- impl<'a, T> RuntimeApi
- where
- T: ::subxt::Config + ::subxt::ExtrinsicExtraData,
- {
- pub fn storage(&'a self) -> StorageApi<'a, T> {
- StorageApi { client: &self.client }
- }
-
- pub fn tx(&'a self) -> TransactionApi<'a, T> {
- TransactionApi { client: &self.client }
- }
- }
-
- pub struct StorageApi<'a, T>
- where
- T: ::subxt::Config + ::subxt::ExtrinsicExtraData,
- {
- client: &'a ::subxt::Client,
- }
-
- impl<'a, T> StorageApi<'a, T>
- where
- T: ::subxt::Config + ::subxt::ExtrinsicExtraData,
- {
- #(
- pub fn #pallets_with_storage(&self) -> #pallets_with_storage::storage::StorageApi<'a, T> {
- #pallets_with_storage::storage::StorageApi::new(self.client)
- }
- )*
- }
-
- pub struct TransactionApi<'a, T: ::subxt::Config + ::subxt::ExtrinsicExtraData> {
- client: &'a ::subxt::Client,
- }
-
- impl<'a, T> TransactionApi<'a, T>
- where
- T: ::subxt::Config + ::subxt::ExtrinsicExtraData,
- {
- #(
- pub fn #pallets_with_calls(&self) -> #pallets_with_calls::calls::TransactionApi<'a, T> {
- #pallets_with_calls::calls::TransactionApi::new(self.client)
- }
- )*
- }
- }
- }
- }
-}
-
-pub fn generate_structs_from_variants(
- type_gen: &TypeGenerator,
- type_id: u32,
- error_message_type_name: &str,
-) -> Vec {
- let ty = type_gen.resolve_type(type_id);
- if let scale_info::TypeDef::Variant(variant) = ty.type_def() {
- variant
- .variants()
- .iter()
- .map(|var| {
- StructDef::new(
- var.name(),
- var.fields(),
- Some(syn::parse_quote!(pub)),
- type_gen,
- )
- })
- .collect()
- } else {
- abort_call_site!(
- "{} type should be an variant/enum type",
- error_message_type_name
- )
- }
-}
diff --git a/codegen/src/api/storage.rs b/codegen/src/api/storage.rs
deleted file mode 100644
index 22310f30ae..0000000000
--- a/codegen/src/api/storage.rs
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright 2019-2021 Parity Technologies (UK) Ltd.
-// This file is part of subxt.
-//
-// subxt is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// subxt is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with subxt. If not, see .
-
-use crate::types::TypeGenerator;
-use frame_metadata::{
- PalletMetadata,
- PalletStorageMetadata,
- StorageEntryMetadata,
- StorageEntryModifier,
- StorageEntryType,
- StorageHasher,
-};
-use heck::SnakeCase as _;
-use proc_macro2::TokenStream as TokenStream2;
-use proc_macro_error::abort_call_site;
-use quote::{
- format_ident,
- quote,
-};
-use scale_info::{
- form::PortableForm,
- TypeDef,
-};
-
-pub fn generate_storage(
- type_gen: &TypeGenerator,
- pallet: &PalletMetadata,
- storage: &PalletStorageMetadata,
- types_mod_ident: &syn::Ident,
-) -> TokenStream2 {
- let (storage_structs, storage_fns): (Vec<_>, Vec<_>) = storage
- .entries
- .iter()
- .map(|entry| generate_storage_entry_fns(&type_gen, &pallet, entry))
- .unzip();
-
- quote! {
- pub mod storage {
- use super::#types_mod_ident;
- #( #storage_structs )*
-
- pub struct StorageApi<'a, T: ::subxt::Config> {
- client: &'a ::subxt::Client,
- }
-
- impl<'a, T: ::subxt::Config> StorageApi<'a, T> {
- pub fn new(client: &'a ::subxt::Client) -> Self {
- Self { client }
- }
-
- #( #storage_fns )*
- }
- }
- }
-}
-
-fn generate_storage_entry_fns(
- type_gen: &TypeGenerator,
- pallet: &PalletMetadata,
- storage_entry: &StorageEntryMetadata,
-) -> (TokenStream2, TokenStream2) {
- let entry_struct_ident = format_ident!("{}", storage_entry.name);
- let (fields, entry_struct, constructor, key_impl) = match storage_entry.ty {
- StorageEntryType::Plain(_) => {
- let entry_struct = quote!( pub struct #entry_struct_ident; );
- let constructor = quote!( #entry_struct_ident );
- let key_impl = quote!(::subxt::StorageEntryKey::Plain);
- (vec![], entry_struct, constructor, key_impl)
- }
- StorageEntryType::Map {
- ref key,
- ref hashers,
- ..
- } => {
- let key_ty = type_gen.resolve_type(key.id());
- let hashers = hashers
- .iter()
- .map(|hasher| {
- let hasher = match hasher {
- StorageHasher::Blake2_128 => "Blake2_128",
- StorageHasher::Blake2_256 => "Blake2_256",
- StorageHasher::Blake2_128Concat => "Blake2_128Concat",
- StorageHasher::Twox128 => "Twox128",
- StorageHasher::Twox256 => "Twox256",
- StorageHasher::Twox64Concat => "Twox64Concat",
- StorageHasher::Identity => "Identity",
- };
- let hasher = format_ident!("{}", hasher);
- quote!( ::subxt::StorageHasher::#hasher )
- })
- .collect::>();
- match key_ty.type_def() {
- TypeDef::Tuple(tuple) => {
- let fields = tuple
- .fields()
- .iter()
- .enumerate()
- .map(|(i, f)| {
- let field_name = format_ident!("_{}", syn::Index::from(i));
- let field_type = type_gen.resolve_type_path(f.id(), &[]);
- (field_name, field_type)
- })
- .collect::>();
- // toddo: [AJ] use unzip here?
- let tuple_struct_fields =
- fields.iter().map(|(_, field_type)| field_type);
- let field_names = fields.iter().map(|(field_name, _)| field_name);
- let entry_struct = quote! {
- pub struct #entry_struct_ident( #( #tuple_struct_fields ),* );
- };
- let constructor =
- quote!( #entry_struct_ident( #( #field_names ),* ) );
- let keys = (0..tuple.fields().len()).into_iter().zip(hashers).map(
- |(field, hasher)| {
- let index = syn::Index::from(field);
- quote!( ::subxt::StorageMapKey::new(&self.#index, #hasher) )
- },
- );
- let key_impl = quote! {
- ::subxt::StorageEntryKey::Map(
- vec![ #( #keys ),* ]
- )
- };
- (fields, entry_struct, constructor, key_impl)
- }
- _ => {
- let ty_path = type_gen.resolve_type_path(key.id(), &[]);
- let fields = vec![(format_ident!("_0"), ty_path.clone())];
- let entry_struct = quote! {
- pub struct #entry_struct_ident( pub #ty_path );
- };
- let constructor = quote!( #entry_struct_ident(_0) );
- let hasher = hashers.get(0).unwrap_or_else(|| {
- abort_call_site!("No hasher found for single key")
- });
- let key_impl = quote! {
- ::subxt::StorageEntryKey::Map(
- vec![ ::subxt::StorageMapKey::new(&self.0, #hasher) ]
- )
- };
- (fields, entry_struct, constructor, key_impl)
- }
- }
- }
- };
- let pallet_name = &pallet.name;
- let storage_name = &storage_entry.name;
- let fn_name = format_ident!("{}", storage_entry.name.to_snake_case());
- let fn_name_iter = format_ident!("{}_iter", fn_name);
- let storage_entry_ty = match storage_entry.ty {
- StorageEntryType::Plain(ref ty) => ty,
- StorageEntryType::Map { ref value, .. } => value,
- };
- let storage_entry_value_ty = type_gen.resolve_type_path(storage_entry_ty.id(), &[]);
- let (return_ty, fetch) = match storage_entry.modifier {
- StorageEntryModifier::Default => {
- (quote!( #storage_entry_value_ty ), quote!(fetch_or_default))
- }
- StorageEntryModifier::Optional => {
- (
- quote!( ::core::option::Option<#storage_entry_value_ty> ),
- quote!(fetch),
- )
- }
- };
-
- let storage_entry_type = quote! {
- #entry_struct
-
- impl ::subxt::StorageEntry for #entry_struct_ident {
- const PALLET: &'static str = #pallet_name;
- const STORAGE: &'static str = #storage_name;
- type Value = #storage_entry_value_ty;
- fn key(&self) -> ::subxt::StorageEntryKey {
- #key_impl
- }
- }
- };
-
- let client_iter_fn = if matches!(storage_entry.ty, StorageEntryType::Map { .. }) {
- quote! (
- pub async fn #fn_name_iter(
- &self,
- hash: ::core::option::Option,
- ) -> ::core::result::Result<::subxt::KeyIter<'a, T, #entry_struct_ident>, ::subxt::Error> {
- self.client.storage().iter(hash).await
- }
- )
- } else {
- quote!()
- };
-
- let key_args = fields
- .iter()
- .map(|(field_name, field_type)| quote!( #field_name: #field_type ));
- let client_fns = quote! {
- pub async fn #fn_name(
- &self,
- #( #key_args, )*
- hash: ::core::option::Option,
- ) -> ::core::result::Result<#return_ty, ::subxt::Error> {
- let entry = #constructor;
- self.client.storage().#fetch(&entry, hash).await
- }
-
- #client_iter_fn
- };
-
- (storage_entry_type, client_fns)
-}
diff --git a/codegen/src/derives.rs b/codegen/src/derives.rs
deleted file mode 100644
index a27319b923..0000000000
--- a/codegen/src/derives.rs
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2019-2021 Parity Technologies (UK) Ltd.
-// This file is part of subxt.
-//
-// subxt is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// subxt is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with subxt. If not, see .
-
-use syn::punctuated::Punctuated;
-
-#[derive(Debug, Clone)]
-pub struct GeneratedTypeDerives {
- derives: Punctuated,
-}
-
-impl GeneratedTypeDerives {
- pub fn new(derives: Punctuated) -> Self {
- Self { derives }
- }
-
- pub fn append(&mut self, derives: impl Iterator- ) {
- for derive in derives {
- self.derives.push(derive)
- }
- }
-}
-
-impl Default for GeneratedTypeDerives {
- fn default() -> Self {
- let mut derives = Punctuated::new();
- derives.push(syn::parse_quote!(::subxt::codec::Encode));
- derives.push(syn::parse_quote!(::subxt::codec::Decode));
- Self::new(derives)
- }
-}
-
-impl quote::ToTokens for GeneratedTypeDerives {
- fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
- let derives = &self.derives;
- tokens.extend(quote::quote! {
- #[derive(#derives)]
- })
- }
-}
diff --git a/codegen/src/ir.rs b/codegen/src/ir.rs
deleted file mode 100644
index 429d0d9acd..0000000000
--- a/codegen/src/ir.rs
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright 2019-2021 Parity Technologies (UK) Ltd.
-// This file is part of subxt.
-//
-// subxt is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// subxt is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with subxt. If not, see .
-
-use proc_macro_error::abort;
-use std::collections::HashMap;
-use syn::{
- spanned::Spanned as _,
- token,
-};
-
-#[derive(Debug, PartialEq, Eq)]
-pub struct ItemMod {
- // attrs: Vec,
- vis: syn::Visibility,
- mod_token: token::Mod,
- pub ident: syn::Ident,
- brace: token::Brace,
- items: Vec
- ,
-}
-
-impl From for ItemMod {
- fn from(module: syn::ItemMod) -> Self {
- let (brace, items) = match module.content {
- Some((brace, items)) => (brace, items),
- None => {
- abort!(module, "out-of-line subxt modules are not supported",)
- }
- };
- let items = items
- .into_iter()
- .map(
- >::from)
- .collect::>();
- Self {
- vis: module.vis,
- mod_token: module.mod_token,
- ident: module.ident,
- brace,
- items,
- }
- }
-}
-
-impl ItemMod {
- pub fn type_substitutes(&self) -> HashMap {
- self.items
- .iter()
- .filter_map(|item| {
- if let Item::Subxt(SubxtItem::TypeSubstitute {
- generated_type_path,
- substitute_with: substitute_type,
- }) = item
- {
- Some((generated_type_path.clone(), substitute_type.clone()))
- } else {
- None
- }
- })
- .collect()
- }
-}
-
-#[derive(Debug, PartialEq, Eq)]
-pub enum Item {
- Rust(syn::Item),
- Subxt(SubxtItem),
-}
-
-impl From for Item {
- fn from(item: syn::Item) -> Self {
- if let syn::Item::Use(ref use_) = item {
- let substitute_attrs = use_
- .attrs
- .iter()
- .map(|attr| {
- let meta = attr.parse_meta().unwrap_or_else(|e| {
- abort!(attr.span(), "Error parsing attribute: {}", e)
- });
- let substitute_type_args =
- ::from_meta(&meta)
- .unwrap_or_else(|e| {
- abort!(attr.span(), "Error parsing attribute meta: {}", e)
- });
- substitute_type_args
- })
- .collect::>();
- if substitute_attrs.len() > 1 {
- abort!(
- use_.attrs[0].span(),
- "Duplicate `substitute_type` attributes"
- )
- }
- if let Some(attr) = substitute_attrs.iter().next() {
- let use_path = &use_.tree;
- let substitute_with: syn::TypePath = syn::parse_quote!( #use_path );
- let type_substitute = SubxtItem::TypeSubstitute {
- generated_type_path: attr.substitute_type().to_string(),
- substitute_with,
- };
- Self::Subxt(type_substitute)
- } else {
- Self::Rust(item)
- }
- } else {
- Self::Rust(item)
- }
- }
-}
-
-#[derive(Debug, PartialEq, Eq)]
-pub enum SubxtItem {
- TypeSubstitute {
- generated_type_path: String,
- substitute_with: syn::TypePath,
- },
-}
-
-mod attrs {
- use darling::FromMeta;
-
- #[derive(Debug, FromMeta)]
- #[darling(rename_all = "snake_case")]
- pub enum Subxt {
- SubstituteType(String),
- }
-
- impl Subxt {
- pub fn substitute_type(&self) -> String {
- match self {
- Self::SubstituteType(path) => path.clone(),
- }
- }
- }
-}
diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs
index 7c65ecdf5a..626d30c471 100644
--- a/codegen/src/lib.rs
+++ b/codegen/src/lib.rs
@@ -14,18 +14,4 @@
// You should have received a copy of the GNU General Public License
// along with subxt. If not, see .
-//! Library to generate an API for a Substrate runtime from its metadata.
-
-mod api;
-mod derives;
-mod ir;
-mod struct_def;
-mod types;
-
-pub use self::{
- api::{
- generate_runtime_api,
- RuntimeGenerator,
- },
- derives::GeneratedTypeDerives,
-};
+//! Library to generate an API for a Substrate runtime from its metadata.
\ No newline at end of file
diff --git a/codegen/src/struct_def.rs b/codegen/src/struct_def.rs
deleted file mode 100644
index 1db6c02b13..0000000000
--- a/codegen/src/struct_def.rs
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright 2019-2021 Parity Technologies (UK) Ltd.
-// This file is part of subxt.
-//
-// subxt is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// subxt is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with subxt. If not, see .
-
-use super::GeneratedTypeDerives;
-use crate::types::{
- TypeGenerator,
- TypePath,
-};
-use heck::CamelCase as _;
-use proc_macro2::TokenStream as TokenStream2;
-use proc_macro_error::abort_call_site;
-use quote::{
- format_ident,
- quote,
-};
-use scale_info::form::PortableForm;
-
-#[derive(Debug)]
-pub struct StructDef {
- pub name: syn::Ident,
- pub fields: StructDefFields,
- pub field_visibility: Option,
- pub derives: GeneratedTypeDerives,
-}
-
-#[derive(Debug)]
-pub enum StructDefFields {
- Named(Vec<(syn::Ident, TypePath)>),
- Unnamed(Vec),
-}
-
-impl StructDef {
- pub fn new(
- ident: &str,
- fields: &[scale_info::Field],
- field_visibility: Option,
- type_gen: &TypeGenerator,
- ) -> Self {
- let name = format_ident!("{}", ident.to_camel_case());
- let fields = fields
- .iter()
- .map(|field| {
- let name = field.name().map(|f| format_ident!("{}", f));
- let ty = type_gen.resolve_type_path(field.ty().id(), &[]);
- (name, ty)
- })
- .collect::>();
-
- let named = fields.iter().all(|(name, _)| name.is_some());
- let unnamed = fields.iter().all(|(name, _)| name.is_none());
-
- let fields = if named {
- StructDefFields::Named(
- fields
- .iter()
- .map(|(name, field)| {
- let name = name.as_ref().unwrap_or_else(|| {
- abort_call_site!("All fields should have a name")
- });
- (name.clone(), field.clone())
- })
- .collect(),
- )
- } else if unnamed {
- StructDefFields::Unnamed(
- fields.iter().map(|(_, field)| field.clone()).collect(),
- )
- } else {
- abort_call_site!(
- "Struct '{}': Fields should either be all named or all unnamed.",
- name,
- )
- };
-
- let derives = type_gen.derives().clone();
-
- Self {
- name,
- fields,
- field_visibility,
- derives,
- }
- }
-
- pub fn named_fields(&self) -> Option<&[(syn::Ident, TypePath)]> {
- if let StructDefFields::Named(ref fields) = self.fields {
- Some(fields)
- } else {
- None
- }
- }
-}
-
-impl quote::ToTokens for StructDef {
- fn to_tokens(&self, tokens: &mut TokenStream2) {
- let visibility = &self.field_visibility;
- let derives = &self.derives;
- tokens.extend(match self.fields {
- StructDefFields::Named(ref named_fields) => {
- let fields = named_fields.iter().map(|(name, ty)| {
- let compact_attr =
- ty.is_compact().then(|| quote!( #[codec(compact)] ));
- quote! { #compact_attr #visibility #name: #ty }
- });
- let name = &self.name;
- quote! {
- #derives
- pub struct #name {
- #( #fields ),*
- }
- }
- }
- StructDefFields::Unnamed(ref unnamed_fields) => {
- let fields = unnamed_fields.iter().map(|ty| {
- let compact_attr =
- ty.is_compact().then(|| quote!( #[codec(compact)] ));
- quote! { #compact_attr #visibility #ty }
- });
- let name = &self.name;
- quote! {
- #derives
- pub struct #name (
- #( #fields ),*
- );
- }
- }
- })
- }
-}
diff --git a/codegen/src/types/mod.rs b/codegen/src/types/mod.rs
deleted file mode 100644
index 73b8b9d062..0000000000
--- a/codegen/src/types/mod.rs
+++ /dev/null
@@ -1,253 +0,0 @@
-// Copyright 2019-2021 Parity Technologies (UK) Ltd.
-// This file is part of subxt.
-//
-// subxt is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// subxt is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with subxt. If not, see .
-
-#[cfg(test)]
-mod tests;
-mod type_def;
-mod type_path;
-
-use super::GeneratedTypeDerives;
-use proc_macro2::{
- Ident,
- Span,
- TokenStream,
-};
-use quote::{
- quote,
- ToTokens,
-};
-use scale_info::{
- form::PortableForm,
- PortableRegistry,
- Type,
- TypeDef,
-};
-use std::collections::{
- BTreeMap,
- HashMap,
-};
-
-pub use self::{
- type_def::TypeDefGen,
- type_path::{
- TypeParameter,
- TypePath,
- TypePathSubstitute,
- TypePathType,
- },
-};
-
-/// Generate a Rust module containing all types defined in the supplied [`PortableRegistry`].
-#[derive(Debug)]
-pub struct TypeGenerator<'a> {
- /// The name of the module which will contain the generated types.
- types_mod_ident: Ident,
- /// Registry of type definitions to be transformed into Rust type definitions.
- type_registry: &'a PortableRegistry,
- /// User defined overrides for generated types.
- type_substitutes: HashMap,
- /// Set of derives with which to annotate generated types.
- derives: GeneratedTypeDerives,
-}
-
-impl<'a> TypeGenerator<'a> {
- /// Construct a new [`TypeGenerator`].
- pub fn new(
- type_registry: &'a PortableRegistry,
- root_mod: &'static str,
- type_substitutes: HashMap,
- derives: GeneratedTypeDerives,
- ) -> Self {
- let root_mod_ident = Ident::new(root_mod, Span::call_site());
- Self {
- types_mod_ident: root_mod_ident,
- type_registry,
- type_substitutes,
- derives,
- }
- }
-
- /// Generate a module containing all types defined in the supplied type registry.
- pub fn generate_types_mod(&'a self) -> Module<'a> {
- let mut root_mod =
- Module::new(self.types_mod_ident.clone(), self.types_mod_ident.clone());
-
- for (id, ty) in self.type_registry.types().iter().enumerate() {
- if ty.ty().path().namespace().is_empty() {
- // prelude types e.g. Option/Result have no namespace, so we don't generate them
- continue
- }
- self.insert_type(
- ty.ty().clone(),
- id as u32,
- ty.ty().path().namespace().to_vec(),
- &self.types_mod_ident,
- &mut root_mod,
- )
- }
-
- root_mod
- }
-
- fn insert_type(
- &'a self,
- ty: Type,
- id: u32,
- path: Vec,
- root_mod_ident: &Ident,
- module: &mut Module<'a>,
- ) {
- let joined_path = path.join("::");
- if self.type_substitutes.contains_key(&joined_path) {
- return
- }
-
- let segment = path.first().expect("path has at least one segment");
- let mod_ident = Ident::new(segment, Span::call_site());
-
- let child_mod = module
- .children
- .entry(mod_ident.clone())
- .or_insert_with(|| Module::new(mod_ident, root_mod_ident.clone()));
-
- if path.len() == 1 {
- child_mod
- .types
- .insert(ty.path().clone(), TypeDefGen { ty, type_gen: self });
- } else {
- self.insert_type(ty, id, path[1..].to_vec(), root_mod_ident, child_mod)
- }
- }
-
- /// # Panics
- ///
- /// If no type with the given id found in the type registry.
- pub fn resolve_type(&self, id: u32) -> Type {
- self.type_registry
- .resolve(id)
- .unwrap_or_else(|| panic!("No type with id {} found", id))
- .clone()
- }
-
- /// # Panics
- ///
- /// If no type with the given id found in the type registry.
- pub fn resolve_type_path(
- &self,
- id: u32,
- parent_type_params: &[TypeParameter],
- ) -> TypePath {
- if let Some(parent_type_param) = parent_type_params
- .iter()
- .find(|tp| tp.concrete_type_id == id)
- {
- return TypePath::Parameter(parent_type_param.clone())
- }
-
- let mut ty = self.resolve_type(id);
-
- if ty.path().ident() == Some("Cow".to_string()) {
- ty = self.resolve_type(
- ty.type_params()[0]
- .ty()
- .expect("type parameters to Cow are not expected to be skipped; qed")
- .id(),
- )
- }
-
- let params_type_ids = match ty.type_def() {
- TypeDef::Array(arr) => vec![arr.type_param().id()],
- TypeDef::Sequence(seq) => vec![seq.type_param().id()],
- TypeDef::Tuple(tuple) => tuple.fields().iter().map(|f| f.id()).collect(),
- TypeDef::Compact(compact) => vec![compact.type_param().id()],
- TypeDef::BitSequence(seq) => {
- vec![seq.bit_order_type().id(), seq.bit_store_type().id()]
- }
- _ => {
- ty.type_params()
- .iter()
- .filter_map(|f| f.ty().map(|f| f.id()))
- .collect()
- }
- };
-
- let params = params_type_ids
- .iter()
- .map(|tp| self.resolve_type_path(*tp, parent_type_params))
- .collect::>();
-
- let joined_path = ty.path().segments().join("::");
- if let Some(substitute_type_path) = self.type_substitutes.get(&joined_path) {
- TypePath::Substitute(TypePathSubstitute {
- path: substitute_type_path.clone(),
- params,
- })
- } else {
- TypePath::Type(TypePathType {
- ty,
- params,
- root_mod_ident: self.types_mod_ident.clone(),
- })
- }
- }
-
- /// Returns the derives with which all generated type will be decorated.
- pub fn derives(&self) -> &GeneratedTypeDerives {
- &self.derives
- }
-}
-
-#[derive(Debug)]
-pub struct Module<'a> {
- name: Ident,
- root_mod: Ident,
- children: BTreeMap>,
- types: BTreeMap, TypeDefGen<'a>>,
-}
-
-impl<'a> ToTokens for Module<'a> {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- let name = &self.name;
- let root_mod = &self.root_mod;
- let modules = self.children.values();
- let types = self.types.values().clone();
-
- tokens.extend(quote! {
- pub mod #name {
- use super::#root_mod;
-
- #( #modules )*
- #( #types )*
- }
- })
- }
-}
-
-impl<'a> Module<'a> {
- pub fn new(name: Ident, root_mod: Ident) -> Self {
- Self {
- name,
- root_mod,
- children: BTreeMap::new(),
- types: BTreeMap::new(),
- }
- }
-
- /// Returns the module ident.
- pub fn ident(&self) -> &Ident {
- &self.name
- }
-}
diff --git a/codegen/src/types/tests.rs b/codegen/src/types/tests.rs
deleted file mode 100644
index 94acde4684..0000000000
--- a/codegen/src/types/tests.rs
+++ /dev/null
@@ -1,799 +0,0 @@
-// Copyright 2019-2021 Parity Technologies (UK) Ltd.
-// This file is part of subxt.
-//
-// subxt is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// subxt is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with subxt. If not, see .
-
-use super::*;
-use pretty_assertions::assert_eq;
-use scale_info::{
- meta_type,
- Registry,
- TypeInfo,
-};
-
-const MOD_PATH: &'static [&'static str] = &["subxt_codegen", "types", "tests"];
-
-fn get_mod<'a>(module: &'a Module, path_segs: &[&'static str]) -> Option<&'a Module<'a>> {
- let (mod_name, rest) = path_segs.split_first()?;
- let mod_ident = Ident::new(mod_name, Span::call_site());
- let module = module.children.get(&mod_ident)?;
- if rest.is_empty() {
- Some(module)
- } else {
- get_mod(module, rest)
- }
-}
-
-#[test]
-fn generate_struct_with_primitives() {
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct S {
- a: bool,
- b: u32,
- c: char,
- }
-
- let mut registry = Registry::new();
- registry.register_type(&meta_type::
());
- let portable_types: PortableRegistry = registry.into();
-
- let type_gen = TypeGenerator::new(
- &portable_types,
- "root",
- Default::default(),
- Default::default(),
- );
- let types = type_gen.generate_types_mod();
- let tests_mod = get_mod(&types, MOD_PATH).unwrap();
-
- assert_eq!(
- tests_mod.into_token_stream().to_string(),
- quote! {
- pub mod tests {
- use super::root;
-
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct S {
- pub a: ::core::primitive::bool,
- pub b: ::core::primitive::u32,
- pub c: ::core::primitive::char,
- }
- }
- }
- .to_string()
- )
-}
-
-#[test]
-fn generate_struct_with_a_struct_field() {
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct Parent {
- a: bool,
- b: Child,
- }
-
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct Child {
- a: i32,
- }
-
- let mut registry = Registry::new();
- registry.register_type(&meta_type::());
- let portable_types: PortableRegistry = registry.into();
-
- let type_gen = TypeGenerator::new(
- &portable_types,
- "root",
- Default::default(),
- Default::default(),
- );
- let types = type_gen.generate_types_mod();
- let tests_mod = get_mod(&types, MOD_PATH).unwrap();
-
- assert_eq!(
- tests_mod.into_token_stream().to_string(),
- quote! {
- pub mod tests {
- use super::root;
-
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct Child {
- pub a: ::core::primitive::i32,
- }
-
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct Parent {
- pub a: ::core::primitive::bool,
- pub b: root::subxt_codegen::types::tests::Child,
- }
- }
- }
- .to_string()
- )
-}
-
-#[test]
-fn generate_tuple_struct() {
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct Parent(bool, Child);
-
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct Child(i32);
-
- let mut registry = Registry::new();
- registry.register_type(&meta_type::());
- let portable_types: PortableRegistry = registry.into();
-
- let type_gen = TypeGenerator::new(
- &portable_types,
- "root",
- Default::default(),
- Default::default(),
- );
- let types = type_gen.generate_types_mod();
- let tests_mod = get_mod(&types, MOD_PATH).unwrap();
-
- assert_eq!(
- tests_mod.into_token_stream().to_string(),
- quote! {
- pub mod tests {
- use super::root;
-
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct Child(pub ::core::primitive::i32,);
-
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct Parent(pub ::core::primitive::bool, pub root::subxt_codegen::types::tests::Child,);
- }
- }
- .to_string()
- )
-}
-
-#[test]
-fn derive_compact_as_for_uint_wrapper_structs() {
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct Su8 {
- a: u8,
- }
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct TSu8(u8);
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct Su16 {
- a: u16,
- }
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct TSu16(u16);
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct Su32 {
- a: u32,
- }
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct TSu32(u32);
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct Su64 {
- a: u64,
- }
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct TSu64(u64);
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct Su128 {
- a: u128,
- }
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct TSu128(u128);
-
- let mut registry = Registry::new();
- registry.register_type(&meta_type::());
- registry.register_type(&meta_type::());
- registry.register_type(&meta_type::());
- registry.register_type(&meta_type::());
- registry.register_type(&meta_type::());
- registry.register_type(&meta_type::());
- registry.register_type(&meta_type::());
- registry.register_type(&meta_type::());
- registry.register_type(&meta_type::());
- registry.register_type(&meta_type::());
- let portable_types: PortableRegistry = registry.into();
-
- let type_gen = TypeGenerator::new(
- &portable_types,
- "root",
- Default::default(),
- Default::default(),
- );
- let types = type_gen.generate_types_mod();
- let tests_mod = get_mod(&types, MOD_PATH).unwrap();
-
- assert_eq!(
- tests_mod.into_token_stream().to_string(),
- quote! {
- pub mod tests {
- use super::root;
-
- #[derive(::subxt::codec::CompactAs)]
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct Su128 { pub a: ::core::primitive::u128, }
-
- #[derive(::subxt::codec::CompactAs)]
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct Su16 { pub a: ::core::primitive::u16, }
-
- #[derive(::subxt::codec::CompactAs)]
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct Su32 { pub a: ::core::primitive::u32, }
-
- #[derive(::subxt::codec::CompactAs)]
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct Su64 { pub a: ::core::primitive::u64, }
-
- #[derive(::subxt::codec::CompactAs)]
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct Su8 { pub a: ::core::primitive::u8, }
-
- #[derive(::subxt::codec::CompactAs)]
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct TSu128(pub ::core::primitive::u128,);
-
- #[derive(::subxt::codec::CompactAs)]
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct TSu16(pub ::core::primitive::u16,);
-
- #[derive(::subxt::codec::CompactAs)]
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct TSu32(pub ::core::primitive::u32,);
-
- #[derive(::subxt::codec::CompactAs)]
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct TSu64(pub ::core::primitive::u64,);
-
- #[derive(::subxt::codec::CompactAs)]
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct TSu8(pub ::core::primitive::u8,);
- }
- }
- .to_string()
- )
-}
-
-#[test]
-fn generate_enum() {
- #[allow(unused)]
- #[derive(TypeInfo)]
- enum E {
- A,
- B(bool),
- C { a: u32 },
- }
-
- let mut registry = Registry::new();
- registry.register_type(&meta_type::());
- let portable_types: PortableRegistry = registry.into();
-
- let type_gen = TypeGenerator::new(
- &portable_types,
- "root",
- Default::default(),
- Default::default(),
- );
- let types = type_gen.generate_types_mod();
- let tests_mod = get_mod(&types, MOD_PATH).unwrap();
-
- assert_eq!(
- tests_mod.into_token_stream().to_string(),
- quote! {
- pub mod tests {
- use super::root;
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub enum E {
- # [codec (index = 0)]
- A,
- # [codec (index = 1)]
- B (::core::primitive::bool,),
- # [codec (index = 2)]
- C { a: ::core::primitive::u32, },
- }
- }
- }
- .to_string()
- )
-}
-
-#[test]
-fn generate_array_field() {
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct S {
- a: [u8; 32],
- }
-
- let mut registry = Registry::new();
- registry.register_type(&meta_type::());
- let portable_types: PortableRegistry = registry.into();
-
- let type_gen = TypeGenerator::new(
- &portable_types,
- "root",
- Default::default(),
- Default::default(),
- );
- let types = type_gen.generate_types_mod();
- let tests_mod = get_mod(&types, MOD_PATH).unwrap();
-
- assert_eq!(
- tests_mod.into_token_stream().to_string(),
- quote! {
- pub mod tests {
- use super::root;
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct S {
- pub a: [::core::primitive::u8; 32usize],
- }
- }
- }
- .to_string()
- )
-}
-
-#[test]
-fn option_fields() {
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct S {
- a: Option,
- b: Option,
- }
-
- let mut registry = Registry::new();
- registry.register_type(&meta_type::());
- let portable_types: PortableRegistry = registry.into();
-
- let type_gen = TypeGenerator::new(
- &portable_types,
- "root",
- Default::default(),
- Default::default(),
- );
- let types = type_gen.generate_types_mod();
- let tests_mod = get_mod(&types, MOD_PATH).unwrap();
-
- assert_eq!(
- tests_mod.into_token_stream().to_string(),
- quote! {
- pub mod tests {
- use super::root;
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct S {
- pub a: ::core::option::Option<::core::primitive::bool>,
- pub b: ::core::option::Option<::core::primitive::u32>,
- }
- }
- }
- .to_string()
- )
-}
-
-#[test]
-fn box_fields_struct() {
- use std::boxed::Box;
-
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct S {
- a: std::boxed::Box,
- b: Box,
- }
-
- let mut registry = Registry::new();
- registry.register_type(&meta_type::());
- let portable_types: PortableRegistry = registry.into();
-
- let type_gen = TypeGenerator::new(
- &portable_types,
- "root",
- Default::default(),
- Default::default(),
- );
- let types = type_gen.generate_types_mod();
- let tests_mod = get_mod(&types, MOD_PATH).unwrap();
-
- assert_eq!(
- tests_mod.into_token_stream().to_string(),
- quote! {
- pub mod tests {
- use super::root;
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct S {
- pub a: ::std::boxed::Box<::core::primitive::bool>,
- pub b: ::std::boxed::Box<::core::primitive::u32>,
- }
- }
- }
- .to_string()
- )
-}
-
-#[test]
-fn box_fields_enum() {
- use std::boxed::Box;
-
- #[allow(unused)]
- #[derive(TypeInfo)]
- enum E {
- A(Box),
- B { a: Box },
- }
-
- let mut registry = Registry::new();
- registry.register_type(&meta_type::());
- let portable_types: PortableRegistry = registry.into();
-
- let type_gen = TypeGenerator::new(
- &portable_types,
- "root",
- Default::default(),
- Default::default(),
- );
- let types = type_gen.generate_types_mod();
- let tests_mod = get_mod(&types, MOD_PATH).unwrap();
-
- assert_eq!(
- tests_mod.into_token_stream().to_string(),
- quote! {
- pub mod tests {
- use super::root;
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub enum E {
- # [codec (index = 0)]
- A(::std::boxed::Box<::core::primitive::bool>,),
- # [codec (index = 1)]
- B { a: ::std::boxed::Box<::core::primitive::u32>, },
- }
- }
- }
- .to_string()
- )
-}
-
-#[test]
-fn range_fields() {
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct S {
- a: core::ops::Range,
- b: core::ops::RangeInclusive,
- }
-
- let mut registry = Registry::new();
- registry.register_type(&meta_type::());
- let portable_types: PortableRegistry = registry.into();
-
- let type_gen = TypeGenerator::new(
- &portable_types,
- "root",
- Default::default(),
- Default::default(),
- );
- let types = type_gen.generate_types_mod();
- let tests_mod = get_mod(&types, MOD_PATH).unwrap();
-
- assert_eq!(
- tests_mod.into_token_stream().to_string(),
- quote! {
- pub mod tests {
- use super::root;
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct S {
- pub a: ::core::ops::Range<::core::primitive::u32>,
- pub b: ::core::ops::RangeInclusive<::core::primitive::u32>,
- }
- }
- }
- .to_string()
- )
-}
-
-#[test]
-fn generics() {
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct Foo {
- a: T,
- }
-
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct Bar {
- b: Foo,
- c: Foo,
- }
-
- let mut registry = Registry::new();
- registry.register_type(&meta_type::());
- let portable_types: PortableRegistry = registry.into();
-
- let type_gen = TypeGenerator::new(
- &portable_types,
- "root",
- Default::default(),
- Default::default(),
- );
- let types = type_gen.generate_types_mod();
- let tests_mod = get_mod(&types, MOD_PATH).unwrap();
-
- assert_eq!(
- tests_mod.into_token_stream().to_string(),
- quote! {
- pub mod tests {
- use super::root;
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct Bar {
- pub b: root::subxt_codegen::types::tests::Foo<::core::primitive::u32>,
- pub c: root::subxt_codegen::types::tests::Foo<::core::primitive::u8>,
- }
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct Foo<_0> {
- pub a: _0,
- }
- }
- }
- .to_string()
- )
-}
-
-#[test]
-fn generics_nested() {
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct Foo {
- a: T,
- b: Option<(T, U)>,
- }
-
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct Bar {
- b: Foo,
- }
-
- let mut registry = Registry::new();
- registry.register_type(&meta_type::>());
- let portable_types: PortableRegistry = registry.into();
-
- let type_gen = TypeGenerator::new(
- &portable_types,
- "root",
- Default::default(),
- Default::default(),
- );
- let types = type_gen.generate_types_mod();
- let tests_mod = get_mod(&types, MOD_PATH).unwrap();
-
- assert_eq!(
- tests_mod.into_token_stream().to_string(),
- quote! {
- pub mod tests {
- use super::root;
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct Bar<_0> {
- pub b: root::subxt_codegen::types::tests::Foo<_0, ::core::primitive::u32>,
- }
-
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct Foo<_0, _1> {
- pub a: _0,
- pub b: ::core::option::Option<(_0, _1,)>,
- }
- }
- }
- .to_string()
- )
-}
-
-#[test]
-fn generate_bitvec() {
- use bitvec::{
- order::{
- Lsb0,
- Msb0,
- },
- vec::BitVec,
- };
-
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct S {
- lsb: BitVec,
- msb: BitVec,
- }
-
- let mut registry = Registry::new();
- registry.register_type(&meta_type::());
- let portable_types: PortableRegistry = registry.into();
-
- let type_gen = TypeGenerator::new(
- &portable_types,
- "root",
- Default::default(),
- Default::default(),
- );
- let types = type_gen.generate_types_mod();
- let tests_mod = get_mod(&types, MOD_PATH).unwrap();
-
- assert_eq!(
- tests_mod.into_token_stream().to_string(),
- quote! {
- pub mod tests {
- use super::root;
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct S {
- pub lsb: ::subxt::bitvec::vec::BitVec,
- pub msb: ::subxt::bitvec::vec::BitVec,
- }
- }
- }
- .to_string()
- )
-}
-
-#[test]
-fn generics_with_alias_adds_phantom_data_marker() {
- trait Trait {
- type Type;
- }
-
- impl Trait for bool {
- type Type = u32;
- }
-
- type Foo = ::Type;
- type Bar = (::Type, ::Type);
-
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct NamedFields {
- b: Foo,
- }
-
- #[allow(unused)]
- #[derive(TypeInfo)]
- struct UnnamedFields(Bar);
-
- let mut registry = Registry::new();
- registry.register_type(&meta_type::>());
- registry.register_type(&meta_type::>());
- let portable_types: PortableRegistry = registry.into();
-
- let type_gen = TypeGenerator::new(
- &portable_types,
- "root",
- Default::default(),
- Default::default(),
- );
- let types = type_gen.generate_types_mod();
- let tests_mod = get_mod(&types, MOD_PATH).unwrap();
-
- assert_eq!(
- tests_mod.into_token_stream().to_string(),
- quote! {
- pub mod tests {
- use super::root;
- #[derive(::subxt::codec::CompactAs)]
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct NamedFields<_0> {
- pub b: ::core::primitive::u32,
- #[codec(skip)] pub __subxt_unused_type_params: ::core::marker::PhantomData<_0>,
- }
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct UnnamedFields<_0, _1> (
- pub (::core::primitive::u32, ::core::primitive::u32,),
- #[codec(skip)] pub ::core::marker::PhantomData<(_0, _1)>,
- );
- }
- }
- .to_string()
- )
-}
-
-#[test]
-fn modules() {
- mod modules {
- pub mod a {
- #[allow(unused)]
- #[derive(scale_info::TypeInfo)]
- pub struct Foo {}
-
- pub mod b {
- #[allow(unused)]
- #[derive(scale_info::TypeInfo)]
- pub struct Bar {
- a: super::Foo,
- }
- }
- }
-
- pub mod c {
- #[allow(unused)]
- #[derive(scale_info::TypeInfo)]
- pub struct Foo {
- a: super::a::b::Bar,
- }
- }
- }
-
- let mut registry = Registry::new();
- registry.register_type(&meta_type::());
- let portable_types: PortableRegistry = registry.into();
-
- let type_gen = TypeGenerator::new(
- &portable_types,
- "root",
- Default::default(),
- Default::default(),
- );
- let types = type_gen.generate_types_mod();
- let tests_mod = get_mod(&types, MOD_PATH).unwrap();
-
- assert_eq!(
- tests_mod.into_token_stream().to_string(),
- quote! {
- pub mod tests {
- use super::root;
- pub mod modules {
- use super::root;
- pub mod a {
- use super::root;
-
- pub mod b {
- use super::root;
-
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct Bar {
- pub a: root::subxt_codegen::types::tests::modules::a::Foo,
- }
- }
-
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct Foo {}
- }
-
- pub mod c {
- use super::root;
-
- #[derive(::subxt::codec::Encode, ::subxt::codec::Decode)]
- pub struct Foo {
- pub a: root::subxt_codegen::types::tests::modules::a::b::Bar,
- }
- }
- }
- }
- }
- .to_string()
- )
-}
diff --git a/codegen/src/types/type_def.rs b/codegen/src/types/type_def.rs
deleted file mode 100644
index 2c432b88fe..0000000000
--- a/codegen/src/types/type_def.rs
+++ /dev/null
@@ -1,329 +0,0 @@
-// Copyright 2019-2021 Parity Technologies (UK) Ltd.
-// This file is part of subxt.
-//
-// subxt is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// subxt is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with subxt. If not, see .
-
-use super::{
- TypeGenerator,
- TypeParameter,
- TypePath,
-};
-use proc_macro2::TokenStream;
-use quote::{
- format_ident,
- quote,
-};
-use scale_info::{
- form::PortableForm,
- Field,
- Type,
- TypeDef,
- TypeDefPrimitive,
-};
-use std::collections::HashSet;
-use syn::parse_quote;
-
-/// Generates a Rust `struct` or `enum` definition based on the supplied [`scale-info::Type`].
-///
-/// Field type paths are resolved via the `TypeGenerator`, which contains the registry of all
-/// generated types in the module.
-#[derive(Debug)]
-pub struct TypeDefGen<'a> {
- /// The type generation context, allows resolving of type paths for the fields of the
- /// generated type.
- pub(super) type_gen: &'a TypeGenerator<'a>,
- /// Contains the definition of the type to be generated.
- pub(super) ty: Type,
-}
-
-impl<'a> quote::ToTokens for TypeDefGen<'a> {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- let type_params = self
- .ty
- .type_params()
- .iter()
- .enumerate()
- .filter_map(|(i, tp)| {
- match tp.ty() {
- Some(ty) => {
- let tp_name = format_ident!("_{}", i);
- Some(TypeParameter {
- concrete_type_id: ty.id(),
- name: tp_name,
- })
- }
- None => None,
- }
- })
- .collect::>();
-
- let type_name = self.ty.path().ident().map(|ident| {
- let type_params = if !type_params.is_empty() {
- quote! { < #( #type_params ),* > }
- } else {
- quote! {}
- };
- let ty = format_ident!("{}", ident);
- let path = parse_quote! { #ty #type_params};
- syn::Type::Path(path)
- });
-
- let derives = self.type_gen.derives();
-
- match self.ty.type_def() {
- TypeDef::Composite(composite) => {
- let type_name = type_name.expect("structs should have a name");
- let (fields, _) =
- self.composite_fields(composite.fields(), &type_params, true);
- let derive_as_compact = if composite.fields().len() == 1 {
- // any single field wrapper struct with a concrete unsigned int type can derive
- // CompactAs.
- let field = &composite.fields()[0];
- if !self
- .ty
- .type_params()
- .iter()
- .any(|tp| Some(tp.name()) == field.type_name())
- {
- let ty = self.type_gen.resolve_type(field.ty().id());
- if matches!(
- ty.type_def(),
- TypeDef::Primitive(
- TypeDefPrimitive::U8
- | TypeDefPrimitive::U16
- | TypeDefPrimitive::U32
- | TypeDefPrimitive::U64
- | TypeDefPrimitive::U128
- )
- ) {
- Some(quote!( #[derive(::subxt::codec::CompactAs)] ))
- } else {
- None
- }
- } else {
- None
- }
- } else {
- None
- };
-
- let ty_toks = quote! {
- #derive_as_compact
- #derives
- pub struct #type_name #fields
- };
- tokens.extend(ty_toks);
- }
- TypeDef::Variant(variant) => {
- let type_name = type_name.expect("variants should have a name");
- let mut variants = Vec::new();
- let mut used_type_params = HashSet::new();
- let type_params_set: HashSet<_> = type_params.iter().cloned().collect();
-
- for v in variant.variants() {
- let variant_name = format_ident!("{}", v.name());
- let (fields, unused_type_params) = if v.fields().is_empty() {
- let unused = type_params_set.iter().cloned().collect::>();
- (quote! {}, unused)
- } else {
- self.composite_fields(v.fields(), &type_params, false)
- };
- let index = proc_macro2::Literal::u8_unsuffixed(v.index());
- variants.push(quote! {
- #[codec(index = #index)]
- #variant_name #fields
- });
- let unused_params_set = unused_type_params.iter().cloned().collect();
- let used_params = type_params_set.difference(&unused_params_set);
-
- for used_param in used_params {
- used_type_params.insert(used_param.clone());
- }
- }
-
- let unused_type_params = type_params_set
- .difference(&used_type_params)
- .cloned()
- .collect::>();
- if !unused_type_params.is_empty() {
- let phantom = Self::phantom_data(&unused_type_params);
- variants.push(quote! {
- __Ignore(#phantom)
- })
- }
-
- let ty_toks = quote! {
- #derives
- pub enum #type_name {
- #( #variants, )*
- }
- };
- tokens.extend(ty_toks);
- }
- _ => (), // all built-in types should already be in scope
- }
- }
-}
-
-impl<'a> TypeDefGen<'a> {
- fn composite_fields(
- &self,
- fields: &'a [Field],
- type_params: &'a [TypeParameter],
- is_struct: bool,
- ) -> (TokenStream, Vec) {
- let named = fields.iter().all(|f| f.name().is_some());
- let unnamed = fields.iter().all(|f| f.name().is_none());
-
- fn unused_type_params<'a>(
- type_params: &'a [TypeParameter],
- types: impl Iterator- ,
- ) -> Vec {
- let mut used_type_params = HashSet::new();
- for ty in types {
- ty.parent_type_params(&mut used_type_params)
- }
- let type_params_set: HashSet<_> = type_params.iter().cloned().collect();
- let mut unused = type_params_set
- .difference(&used_type_params)
- .cloned()
- .collect::>();
- unused.sort();
- unused
- }
-
- let ty_toks = |ty_name: &str, ty_path: &TypePath| {
- if ty_name.contains("Box<") {
- quote! { ::std::boxed::Box<#ty_path> }
- } else {
- quote! { #ty_path }
- }
- };
-
- if named {
- let fields = fields
- .iter()
- .map(|field| {
- let name = format_ident!(
- "{}",
- field.name().expect("named field without a name")
- );
- let ty = self
- .type_gen
- .resolve_type_path(field.ty().id(), type_params);
- (name, ty, field.type_name())
- })
- .collect::>();
-
- let mut fields_tokens = fields
- .iter()
- .map(|(name, ty, ty_name)| {
- let field_type = match ty_name {
- Some(ty_name) => {
- let ty = ty_toks(ty_name, ty);
- if is_struct {
- quote! ( pub #name: #ty )
- } else {
- quote! ( #name: #ty )
- }
- }
- None => {
- quote! ( #name: #ty )
- }
- };
- if ty.is_compact() {
- quote!( #[codec(compact)] #field_type )
- } else {
- quote!( #field_type )
- }
- })
- .collect::>();
-
- let unused_params =
- unused_type_params(type_params, fields.iter().map(|(_, ty, _)| ty));
-
- if is_struct && !unused_params.is_empty() {
- let phantom = Self::phantom_data(&unused_params);
- fields_tokens.push(quote! {
- #[codec(skip)] pub __subxt_unused_type_params: #phantom
- })
- }
-
- let fields = quote! {
- {
- #( #fields_tokens, )*
- }
- };
- (fields, unused_params)
- } else if unnamed {
- let type_paths = fields
- .iter()
- .map(|field| {
- let ty = self
- .type_gen
- .resolve_type_path(field.ty().id(), type_params);
- (ty, field.type_name())
- })
- .collect::>();
- let mut fields_tokens = type_paths
- .iter()
- .map(|(ty, ty_name)| {
- match ty_name {
- Some(ty_name) => {
- let ty = ty_toks(ty_name, ty);
- if is_struct {
- quote! { pub #ty }
- } else {
- quote! { #ty }
- }
- }
- None => {
- quote! { #ty }
- }
- }
- })
- .collect::>();
-
- let unused_params =
- unused_type_params(type_params, type_paths.iter().map(|(ty, _)| ty));
-
- if is_struct && !unused_params.is_empty() {
- let phantom_data = Self::phantom_data(&unused_params);
- fields_tokens.push(quote! { #[codec(skip)] pub #phantom_data })
- }
-
- let fields = quote! { ( #( #fields_tokens, )* ) };
- let fields_tokens = if is_struct {
- // add a semicolon for tuple structs
- quote! { #fields; }
- } else {
- fields
- };
-
- (fields_tokens, unused_params)
- } else {
- panic!("Fields must be either all named or all unnamed")
- }
- }
-
- fn phantom_data(params: &[TypeParameter]) -> TokenStream {
- let params = if params.len() == 1 {
- let param = ¶ms[0];
- quote! { #param }
- } else {
- quote! { ( #( #params ), * ) }
- };
- quote! ( ::core::marker::PhantomData<#params> )
- }
-}
diff --git a/codegen/src/types/type_path.rs b/codegen/src/types/type_path.rs
deleted file mode 100644
index 186619cbf0..0000000000
--- a/codegen/src/types/type_path.rs
+++ /dev/null
@@ -1,253 +0,0 @@
-// Copyright 2019-2021 Parity Technologies (UK) Ltd.
-// This file is part of subxt.
-//
-// subxt is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// subxt is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with subxt. If not, see .
-
-use proc_macro2::{
- Ident,
- TokenStream,
-};
-use quote::{
- format_ident,
- quote,
-};
-use scale_info::{
- form::PortableForm,
- Type,
- TypeDef,
- TypeDefPrimitive,
-};
-use std::collections::HashSet;
-use syn::parse_quote;
-
-#[derive(Clone, Debug)]
-pub enum TypePath {
- Parameter(TypeParameter),
- Type(TypePathType),
- Substitute(TypePathSubstitute),
-}
-
-impl quote::ToTokens for TypePath {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- let syn_type = self.to_syn_type();
- syn_type.to_tokens(tokens)
- }
-}
-
-impl TypePath {
- pub(crate) fn to_syn_type(&self) -> syn::Type {
- match self {
- TypePath::Parameter(ty_param) => syn::Type::Path(parse_quote! { #ty_param }),
- TypePath::Type(ty) => ty.to_syn_type(),
- TypePath::Substitute(sub) => sub.to_syn_type(),
- }
- }
-
- pub(crate) fn is_compact(&self) -> bool {
- matches!(self, Self::Type(ty) if ty.is_compact())
- }
-
- /// Returns the type parameters in a path which are inherited from the containing type.
- ///
- /// # Example
- ///
- /// ```rust
- /// struct S {
- /// a: Vec