From 6ecd7559a683f7c882209d246836f4604f0ee636 Mon Sep 17 00:00:00 2001 From: Tadeo Hepperle <62739623+tadeohepperle@users.noreply.github.com> Date: Wed, 9 Aug 2023 19:04:02 +0200 Subject: [PATCH] Support more types in Storage entry constructors (#1105) * implement test for type alias being used * Bump serde from 1.0.179 to 1.0.183 (#1112) Bumps [serde](https://github.com/serde-rs/serde) from 1.0.179 to 1.0.183. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.179...v1.0.183) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump regex from 1.9.1 to 1.9.3 (#1110) Bumps [regex](https://github.com/rust-lang/regex) from 1.9.1 to 1.9.3. - [Release notes](https://github.com/rust-lang/regex/releases) - [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/regex/compare/1.9.1...1.9.3) --- updated-dependencies: - dependency-name: regex dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * revert yaml changes --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 66 +++++++-------- Cargo.toml | 4 +- codegen/src/api/storage.rs | 144 ++++++++++++++++++++++++++++++--- codegen/src/types/type_path.rs | 13 +++ 4 files changed, 183 insertions(+), 44 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index af96e64ac8..97ed20e562 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -337,7 +337,7 @@ checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -747,7 +747,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -1118,7 +1118,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -1140,7 +1140,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core 0.20.3", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -1480,7 +1480,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -1992,7 +1992,7 @@ dependencies = [ "subxt-codegen", "subxt-metadata", "subxt-signer", - "syn 2.0.27", + "syn 2.0.28", "test-runtime", "tokio", "tracing", @@ -2674,7 +2674,7 @@ checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -2977,18 +2977,18 @@ checksum = "2dfaf0c85b766276c797f3791f5bc6d5bd116b41d53049af2789666b0c0bc9fa" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] name = "regex" -version = "1.9.1" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.3.3", + "regex-automata 0.3.6", "regex-syntax 0.7.4", ] @@ -3003,9 +3003,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.3" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" +checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" dependencies = [ "aho-corasick", "memchr", @@ -3444,9 +3444,9 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.179" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5bf42b8d227d4abf38a1ddb08602e229108a517cd4e5bb28f9c7eaafdce5c0" +checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" dependencies = [ "serde_derive", ] @@ -3462,13 +3462,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.179" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "741e124f5485c7e60c03b043f79f320bff3527f4bbf12cf3831750dc46a0ec2c" +checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -3833,7 +3833,7 @@ dependencies = [ "proc-macro2", "quote", "sp-core-hashing", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -3844,7 +3844,7 @@ checksum = "c7f531814d2f16995144c74428830ccf7d94ff4a7749632b83ad8199b181140c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -3975,7 +3975,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -4083,7 +4083,7 @@ dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -4270,7 +4270,7 @@ dependencies = [ "subxt", "subxt-codegen", "subxt-metadata", - "syn 2.0.27", + "syn 2.0.28", "tokio", ] @@ -4289,7 +4289,7 @@ dependencies = [ "quote", "scale-info", "subxt-metadata", - "syn 2.0.27", + "syn 2.0.28", "thiserror", "tokio", ] @@ -4327,7 +4327,7 @@ dependencies = [ "darling 0.20.3", "proc-macro-error", "subxt-codegen", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -4380,9 +4380,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.27" +version = "2.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0" +checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" dependencies = [ "proc-macro2", "quote", @@ -4468,7 +4468,7 @@ checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -4560,7 +4560,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -4643,7 +4643,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -4961,7 +4961,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", "wasm-bindgen-shared", ] @@ -4995,7 +4995,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5448,5 +5448,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] diff --git a/Cargo.toml b/Cargo.toml index b747e5e070..2a6599e7ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,13 +60,13 @@ primitive-types = { version = "0.12.1", default-features = false, features = ["c proc-macro-error = "1.0.4" proc-macro2 = "1.0.66" quote = "1.0.31" -regex = "1.9.1" +regex = "1.9.3" scale-info = "2.9.0" scale-value = "0.12.0" scale-bits = "0.4.0" scale-decode = "0.9.0" scale-encode = "0.5.0" -serde = { version = "1.0.179" } +serde = { version = "1.0.183" } serde_json = { version = "1.0.104" } syn = { version = "2.0.15", features = ["full", "extra-traits"] } thiserror = "1.0.40" diff --git a/codegen/src/api/storage.rs b/codegen/src/api/storage.rs index 19ca4ecfb4..9712fe7f35 100644 --- a/codegen/src/api/storage.rs +++ b/codegen/src/api/storage.rs @@ -5,7 +5,7 @@ use crate::types::TypePath; use crate::{types::TypeGenerator, CratePath}; use heck::ToSnakeCase as _; -use proc_macro2::{Ident, TokenStream as TokenStream2}; +use proc_macro2::{Ident, TokenStream as TokenStream2, TokenStream}; use quote::{format_ident, quote}; use scale_info::TypeDef; use subxt_metadata::{ @@ -125,14 +125,7 @@ fn generate_storage_entry_fns( let is_iterable_type = is_iterable.then_some(quote!(#crate_path::storage::address::Yes)).unwrap_or(quote!(())); let key_impls = keys_slice.iter().map(|(field_name, _)| quote!( #crate_path::storage::address::make_static_storage_map_key(#field_name.borrow()) )); let key_args = keys_slice.iter().map(|(field_name, field_type)| { - // The field type is translated from `std::vec::Vec` to `[T]`. We apply - // Borrow to all types, so this just makes it a little more ergonomic. - // TODO [jsdw]: Support mappings like `String -> str` too for better borrow - // ergonomics. - let field_ty = match field_type.vec_type_param() { - Some(ty) => quote!([#ty]), - _ => quote!(#field_type), - }; + let field_ty = primitive_type_alias(field_type); quote!( #field_name: impl ::std::borrow::Borrow<#field_ty> ) }); @@ -164,3 +157,136 @@ fn generate_storage_entry_fns( )* }) } + +fn primitive_type_alias(type_path: &TypePath) -> TokenStream { + // Vec is cast to [T] + if let Some(ty) = type_path.vec_type_param() { + return quote!([#ty]); + } + // String is cast to str + if type_path.is_string() { + return quote!(::core::primitive::str); + } + quote!(#type_path) +} + +#[cfg(test)] +mod tests { + use crate::RuntimeGenerator; + use frame_metadata::v15; + use quote::{format_ident, quote}; + use scale_info::{meta_type, MetaType}; + use std::borrow::Cow; + + use subxt_metadata::Metadata; + + fn metadata_with_storage_entries( + storage_entries: impl IntoIterator, + ) -> Metadata { + let storage_entries: Vec = storage_entries + .into_iter() + .map(|(name, key)| v15::StorageEntryMetadata { + name, + modifier: v15::StorageEntryModifier::Optional, + ty: v15::StorageEntryType::Map { + hashers: vec![], + key, + value: meta_type::(), + }, + default: vec![], + docs: vec![], + }) + .collect(); + + let pallet_1 = v15::PalletMetadata { + name: "Pallet1", + storage: Some(v15::PalletStorageMetadata { + prefix: Default::default(), + entries: storage_entries, + }), + calls: None, + event: None, + constants: vec![], + error: None, + index: 0, + docs: vec![], + }; + + let extrinsic_metadata = v15::ExtrinsicMetadata { + version: 0, + signed_extensions: vec![], + address_ty: meta_type::<()>(), + call_ty: meta_type::<()>(), + signature_ty: meta_type::<()>(), + extra_ty: meta_type::<()>(), + }; + + let metadata: Metadata = v15::RuntimeMetadataV15::new( + vec![pallet_1], + extrinsic_metadata, + meta_type::<()>(), + vec![], + v15::OuterEnums { + call_enum_ty: meta_type::<()>(), + event_enum_ty: meta_type::<()>(), + error_enum_ty: meta_type::<()>(), + }, + v15::CustomMetadata { + map: Default::default(), + }, + ) + .try_into() + .expect("can build valid metadata"); + metadata + } + + #[test] + fn borrow_type_replacements() { + let storage_entries = [ + ("vector", meta_type::>()), + ("boxed", meta_type::>()), + ("string", meta_type::()), + ("static_string", meta_type::<&'static str>()), + ("cow_string", meta_type::>()), + ]; + + let expected_borrowed_types = [ + quote!([::core::primitive::u8]), + quote!(::core::primitive::u16), + quote!(::core::primitive::str), + quote!(::core::primitive::str), + quote!(::core::primitive::str), + ]; + + let metadata = metadata_with_storage_entries(storage_entries); + + let item_mod = syn::parse_quote!( + pub mod api {} + ); + let generator = RuntimeGenerator::new(metadata); + let generated = generator + .generate_runtime( + item_mod, + Default::default(), + Default::default(), + "::subxt_path".into(), + false, + ) + .expect("should be able to generate runtime"); + let generated_str = generated.to_string(); + + for ((name, _), expected_type) in storage_entries + .into_iter() + .zip(expected_borrowed_types.into_iter()) + { + let name_ident = format_ident!("{}", name); + let expected_storage_constructor = quote!( + fn #name_ident( + &self, + _0: impl ::std::borrow::Borrow<#expected_type>, + ) + ); + assert!(generated_str.contains(&expected_storage_constructor.to_string())); + } + } +} diff --git a/codegen/src/types/type_path.rs b/codegen/src/types/type_path.rs index def2a6e374..9dafb62b5f 100644 --- a/codegen/src/types/type_path.rs +++ b/codegen/src/types/type_path.rs @@ -61,6 +61,10 @@ impl TypePath { matches!(&self.0, TypePathInner::Type(ty) if ty.is_compact()) } + pub(crate) fn is_string(&self) -> bool { + matches!(&self.0, TypePathInner::Type(ty) if ty.is_string()) + } + /// Returns the type parameters in a path which are inherited from the containing type. /// /// # Example @@ -214,6 +218,15 @@ impl TypePathType { matches!(self, TypePathType::Compact { .. }) } + pub(crate) fn is_string(&self) -> bool { + matches!( + self, + TypePathType::Primitive { + def: TypeDefPrimitive::Str + } + ) + } + fn to_syn_type(&self) -> syn::Type { match &self { TypePathType::Path { path, params } => {