Skip to content

Commit

Permalink
review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
pkhry committed Jan 8, 2025
1 parent 201167d commit 543444c
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 63 deletions.
Empty file.
145 changes: 88 additions & 57 deletions substrate/primitives/api/proc-macro/src/impl_runtime_apis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,29 @@ use std::collections::HashMap;
/// The structure used for parsing the runtime api implementations.
struct RuntimeApiImpls {
impls: Vec<ItemImpl>,
uses: Vec<ItemUse>,
uses: Vec<TypePath>,
}

mod custom_kw {
use syn::custom_keyword;

custom_keyword!(external_impls);
}

impl Parse for RuntimeApiImpls {
fn parse(input: ParseStream) -> Result<Self> {
let mut impls = Vec::new();
let mut uses = Vec::new();
while !input.is_empty() {
if input.peek(syn::Token![use]) || input.peek2(syn::Token![use]) {
let item = input.parse::<ItemUse>()?;
uses.push(item);
if input.peek(custom_kw::external_impls) || input.peek2(syn::Token![!]) {
let content;
input.parse::<custom_kw::external_impls>()?;
input.parse::<syn::Token![!]>()?;
syn::braced!(content in input);
let items = content.parse_terminated(syn::TypePath::parse, syn::Token![,])?;
for item in items.into_iter() {
uses.push(item)
}
} else {
impls.push(input.parse::<ItemImpl>()?);
}
Expand Down Expand Up @@ -221,7 +233,7 @@ fn generate_dispatch_function(impls: &[ItemImpl], kind: Kind) -> Result<TokenStr
.iter()
.map(|x| {
quote::quote! {
if let Some(res) = #x::api::dispatch(method, #data) {
if let Some(res) = #x::internal::api::dispatch(method, #data) {
return Some(res);
}
}
Expand Down Expand Up @@ -806,9 +818,8 @@ fn generate_runtime_api_versions(impls: &[ItemImpl]) -> Result<TokenStream> {
let api_ver = api_ver.map(|a| quote!( #a )).unwrap_or_else(|| base_api_version);
populate_runtime_api_versions(&mut result, &mut sections, attrs, id, api_ver, &c);
}

Ok(quote!(
pub const RUNTIME_API_VERSIONS: #c::ApisVec = #c::create_apis_vec!([ #( #result ),* ]);
pub const PARTIAL_RUNTIME_API_VERSIONS: &[([u8;8], u32)] = &[ #( #result ),* ];

#( #sections )*
))
Expand Down Expand Up @@ -856,9 +867,27 @@ pub fn impl_runtime_apis_impl(input: proc_macro::TokenStream) -> proc_macro::Tok
.into()
}

fn parse_path(path: &mut Vec<Ident>, item: &UseTree) -> Result<()> {
match &item {
syn::UseTree::Path(use_path) => {
path.push(use_path.ident.clone());
parse_path(path, use_path.tree.as_ref())
},
syn::UseTree::Glob(_) => Ok(()),
syn::UseTree::Name(_) | syn::UseTree::Rename(_) | syn::UseTree::Group(_) => {
let error = Error::new(
item.span(),
"Unsupported syntax used to import api implementaions from an extension module. \
Try using `pub use <path>::*` or `use <path>::*`",
);
return Err(error)
},
}
}

fn impl_runtime_apis_impl_inner(
api_impls: &mut [ItemImpl],
uses: &[ItemUse],
uses: &[TypePath],
) -> Result<TokenStream> {
rename_self_in_trait_impls(api_impls);

Expand All @@ -867,49 +896,48 @@ fn impl_runtime_apis_impl_inner(
let runtime_api_versions = generate_runtime_api_versions(api_impls)?;
let wasm_interface = generate_wasm_interface(api_impls)?;
let api_impls_for_runtime_api = generate_api_impl_for_runtime_api(api_impls)?;
let modules = match uses
.iter()
.map(|item| {
let mut path: Vec<Ident> = vec![];
fn call(path: &mut Vec<Ident>, item: &UseTree) -> Result<()> {
match &item {
syn::UseTree::Path(use_path) => {
path.push(use_path.ident.clone());
call(path, use_path.tree.as_ref())
},
syn::UseTree::Glob(_) => Ok(()),
syn::UseTree::Name(_) | syn::UseTree::Rename(_) | syn::UseTree::Group(_) => {
let error = Error::new(
item.span(),
"Unsupported syntax used to import api implementaions from an extension module. \
Try using `pub use <path>::*` or `use <path>::*`",
);
return Err(error)
},
}
}
call(&mut path, &item.tree)?;
let tok = quote::quote! {#(#path)::*};
Ok(syn::parse::<TypePath>(tok.into())
.expect("Can't happen, a valid TypePath was used in the `UseTree`"))
})
.collect::<Result<Vec<TypePath>>>()
.map_err(|e| e.into_compile_error())
{
Ok(items) => items,
Err(e) => return Ok(e),
};
let dispatch_impl = generate_dispatch_function(api_impls, Kind::Main(&modules))?;
let dispatch_impl = generate_dispatch_function(api_impls, Kind::Main(&uses))?;

let runtime_metadata =
crate::runtime_metadata::generate_impl_runtime_metadata(api_impls, Kind::Main(&modules))?;
crate::runtime_metadata::generate_impl_runtime_metadata(api_impls, Kind::Main(&uses))?;

let c = generate_crate_access();

let impl_ = quote!(
let runtime_api_versions_full = quote! {

pub const RUNTIME_API_VERSIONS: #c::ApisVec = {
const LEN: usize = #(#uses::internal::PARTIAL_RUNTIME_API_VERSIONS.len() + )* PARTIAL_RUNTIME_API_VERSIONS.len() + 0;
const ARR: [([u8;8], u32); LEN] = {
let mut arr: [([u8;8], u32); LEN] = [([0;8],0); LEN];
let mut base: usize = 0;
{
let mut i = 0;
while i < PARTIAL_RUNTIME_API_VERSIONS.len() {
arr[base + i] = PARTIAL_RUNTIME_API_VERSIONS[i];
i += 1;
}
base += PARTIAL_RUNTIME_API_VERSIONS.len();
}
#({
let s = #uses::internal::PARTIAL_RUNTIME_API_VERSIONS;
let mut i = 0;
while i < s.len() {
arr[base + i] = s[i];
i += 1;
}
base += s.len();
})*
if base != LEN { panic!("invalid length"); }
arr
};
#c::create_apis_vec!(ARR)
};
};

let impl_ = quote! {
#(
#[allow(unused_imports)]
#uses
pub use #uses::*;
)*

#base_runtime_api
Expand All @@ -922,10 +950,7 @@ fn impl_runtime_apis_impl_inner(

#runtime_metadata

pub fn runtime_api_versions() -> #c::ApisVec {
let api = #c::vec::Vec::from([RUNTIME_API_VERSIONS.into_owned(), #(#modules::RUNTIME_API_VERSIONS.into_owned()),*]).concat();
api.into()
}
#runtime_api_versions_full

pub mod api {
use super::*;
Expand All @@ -934,7 +959,7 @@ fn impl_runtime_apis_impl_inner(

#wasm_interface
}
);
};

let impl_ = expander::Expander::new("impl_runtime_apis")
.dry(std::env::var("EXPAND_MACROS").is_err())
Expand Down Expand Up @@ -963,7 +988,7 @@ pub fn impl_runtime_apis_impl_ext(input: proc_macro::TokenStream) -> proc_macro:
fn impl_runtime_apis_impl_inner_ext(
module: Ident,
api_impls: &mut [ItemImpl],
uses: &[ItemUse],
uses: &[TypePath],
) -> Result<TokenStream> {
rename_self_in_trait_impls(api_impls);
let dispatch_impl = generate_dispatch_function(api_impls, Kind::Ext)?;
Expand All @@ -976,22 +1001,28 @@ fn impl_runtime_apis_impl_inner_ext(
crate::runtime_metadata::generate_impl_runtime_metadata(api_impls, Kind::Ext)?;
let impl_ = quote!(
pub mod #module {
#(#uses)*
#(
pub use #uses::*;
)*

#api_impls_for_runtime

#api_impls_for_runtime_api

#runtime_api_versions
pub mod internal {
use super::*;

#runtime_metadata
#runtime_api_versions

pub mod api {
use super::*;
#runtime_metadata

#dispatch_impl
pub mod api {
use super::*;

#wasm_interface
#dispatch_impl

#wasm_interface
}
}
}
);
Expand Down
4 changes: 2 additions & 2 deletions substrate/primitives/api/proc-macro/src/runtime_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ pub fn generate_impl_runtime_metadata(impls: &[ItemImpl], kind: Kind) -> Result<
#[doc(hidden)]
impl #crate_::metadata_ir::InternalImplRuntimeApis for #runtime_name {
fn runtime_metadata(&self) -> #crate_::vec::Vec<#crate_::metadata_ir::RuntimeApiMetadataIR> {
let other_apis: #crate_::vec::Vec<#crate_::metadata_ir::RuntimeApiMetadataIR> = #crate_::vec::Vec::from([#crate_::vec![ #( #metadata, )*], #(#paths::runtime_metadata(),)*]).concat();
let other_apis: #crate_::vec::Vec<#crate_::metadata_ir::RuntimeApiMetadataIR> = #crate_::vec::Vec::from([#crate_::vec![ #( #metadata, )*], #(#paths::internal::partial_metadata(),)*]).concat();
other_apis
}
}
Expand All @@ -318,7 +318,7 @@ pub fn generate_impl_runtime_metadata(impls: &[ItemImpl], kind: Kind) -> Result<
Kind::Ext => quote! {
#[doc(hidden)]
#[inline(always)]
pub fn runtime_metadata() -> #crate_::vec::Vec<#crate_::metadata_ir::RuntimeApiMetadataIR> {
pub fn partial_metadata() -> #crate_::vec::Vec<#crate_::metadata_ir::RuntimeApiMetadataIR> {
#crate_::vec![ #( #metadata, )* ]
}

Expand Down
23 changes: 19 additions & 4 deletions substrate/primitives/api/test/tests/decl_and_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ decl_runtime_apis! {
fn same_name() -> String;
}

pub trait Example2 {
fn same_name() -> String;
}

#[api_version(2)]
pub trait ApiWithMultipleVersions {
fn stable_one(data: u64);
Expand Down Expand Up @@ -146,20 +150,30 @@ impl_runtime_apis! {
unimplemented!()
}
}

pub use ext::*;
external_impls!{ext, ext2}
}

#[sp_api::impl_runtime_apis_ext]
mod ext {
use super::*;
external_impls! {super}

impl super::Example<Block> for Runtime {
fn same_name() -> String {
"example".to_string()
}
}
}

#[sp_api::impl_runtime_apis_ext]
mod ext2 {
external_impls! {super}
impl super::Example2<Block> for Runtime {
fn same_name() -> String {
"example".to_string()
}
}
}

struct MockApi {
block: Option<Block>,
}
Expand Down Expand Up @@ -251,7 +265,7 @@ fn check_runtime_api_info() {
}

fn check_runtime_api_versions_contains<T: RuntimeApiInfo + ?Sized>() {
assert!(self::runtime_api_versions().iter().any(|v| v == &(T::ID, T::VERSION)));
assert!(RUNTIME_API_VERSIONS.iter().any(|v| v == &(T::ID, T::VERSION)));
}

fn check_staging_runtime_api_versions<T: RuntimeApiInfo + ?Sized>(_staging_ver: u32) {
Expand Down Expand Up @@ -387,4 +401,5 @@ fn runtime_api_metadata_matches_version_implemented() {
#[test]
fn runtime_api_works_with_ext() {
check_runtime_api_versions_contains::<dyn Example<Block>>();
check_runtime_api_versions_contains::<dyn Example2<Block>>();
}

0 comments on commit 543444c

Please sign in to comment.