Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit 6587f62

Browse files
KiChjangchevdor
authored andcommitted
Use proc macros to generate conversion functions for MultiLocation (#3635)
* Use proc macros to generate conversion functions for MultiLocation * Add compile test and missing conversion cases * Add common derives for Parent and Ancestor * Generate conversion functions for MultiLocation v0 via proc macro * Add type conversion test and fix a bug * cargo fmt * Do not hardcode 8 as the number of max parents * Use map instead of for loops when generating code fragments * Spelling * cargo fmt * More mapping, less for-looping
1 parent 50030ea commit 6587f62

File tree

11 files changed

+486
-647
lines changed

11 files changed

+486
-647
lines changed

Cargo.lock

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ members = [
4343
"xcm/xcm-simulator",
4444
"xcm/xcm-simulator/example",
4545
"xcm/pallet-xcm",
46+
"xcm/procedural",
4647
"node/client",
4748
"node/collation-generation",
4849
"node/core/approval-voting",

xcm/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ impl-trait-for-tuples = "0.2.0"
1010
parity-scale-codec = { version = "2.0.0", default-features = false, features = [ "derive" ] }
1111
derivative = {version = "2.2.0", default-features = false, features = [ "use_core" ] }
1212
log = { version = "0.4.14", default-features = false }
13+
xcm-procedural = { path = "procedural" }
1314

1415
[features]
1516
default = ["std"]

xcm/procedural/Cargo.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
authors = ["Parity Technologies <admin@parity.io>"]
3+
name = "xcm-procedural"
4+
version = "0.1.0"
5+
edition = "2018"
6+
7+
[lib]
8+
proc-macro = true
9+
10+
[dependencies]
11+
proc-macro2 = "1.0.28"
12+
quote = "1.0.9"
13+
syn = "1.0.74"

xcm/procedural/src/lib.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2020 Parity Technologies (UK) Ltd.
2+
// This file is part of Polkadot.
3+
4+
// Polkadot is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
9+
// Polkadot is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
14+
// You should have received a copy of the GNU General Public License
15+
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
16+
17+
//! Procedural macros used in XCM.
18+
19+
use proc_macro::TokenStream;
20+
21+
mod v0;
22+
mod v1;
23+
24+
#[proc_macro]
25+
pub fn impl_conversion_functions_for_multilocation_v0(input: TokenStream) -> TokenStream {
26+
v0::multilocation::generate_conversion_functions(input)
27+
.unwrap_or_else(syn::Error::into_compile_error)
28+
.into()
29+
}
30+
31+
#[proc_macro]
32+
pub fn impl_conversion_functions_for_multilocation_v1(input: TokenStream) -> TokenStream {
33+
v1::multilocation::generate_conversion_functions(input)
34+
.unwrap_or_else(syn::Error::into_compile_error)
35+
.into()
36+
}

xcm/procedural/src/v0.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2021 Parity Technologies (UK) Ltd.
2+
// This file is part of Polkadot.
3+
4+
// Polkadot is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
9+
// Polkadot is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
14+
// You should have received a copy of the GNU General Public License
15+
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
16+
17+
pub mod multilocation;
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// Copyright 2021 Parity Technologies (UK) Ltd.
2+
// This file is part of Polkadot.
3+
4+
// Polkadot is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
9+
// Polkadot is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
14+
// You should have received a copy of the GNU General Public License
15+
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
16+
17+
use proc_macro2::{Span, TokenStream};
18+
use quote::{format_ident, quote};
19+
20+
pub fn generate_conversion_functions(input: proc_macro::TokenStream) -> syn::Result<TokenStream> {
21+
if !input.is_empty() {
22+
return Err(syn::Error::new(Span::call_site(), "No arguments expected"))
23+
}
24+
25+
let from_tuples = generate_conversion_from_tuples();
26+
let from_v1 = generate_conversion_from_v1();
27+
28+
Ok(quote! {
29+
#from_tuples
30+
#from_v1
31+
})
32+
}
33+
34+
fn generate_conversion_from_tuples() -> TokenStream {
35+
let from_tuples = (0..8usize)
36+
.map(|num_junctions| {
37+
let junctions =
38+
(0..=num_junctions).map(|_| format_ident!("Junction")).collect::<Vec<_>>();
39+
let idents = (0..=num_junctions).map(|i| format_ident!("j{}", i)).collect::<Vec<_>>();
40+
let variant = &format_ident!("X{}", num_junctions + 1);
41+
let array_size = num_junctions + 1;
42+
43+
quote! {
44+
impl From<( #(#junctions,)* )> for MultiLocation {
45+
fn from( ( #(#idents,)* ): ( #(#junctions,)* ) ) -> Self {
46+
MultiLocation::#variant( #(#idents),* )
47+
}
48+
}
49+
50+
impl From<[Junction; #array_size]> for MultiLocation {
51+
fn from(j: [Junction; #array_size]) -> Self {
52+
let [#(#idents),*] = j;
53+
MultiLocation::#variant( #(#idents),* )
54+
}
55+
}
56+
}
57+
})
58+
.collect::<TokenStream>();
59+
60+
quote! {
61+
impl From<()> for MultiLocation {
62+
fn from(_: ()) -> Self {
63+
MultiLocation::Null
64+
}
65+
}
66+
67+
impl From<Junction> for MultiLocation {
68+
fn from(x: Junction) -> Self {
69+
MultiLocation::X1(x)
70+
}
71+
}
72+
73+
impl From<[Junction; 0]> for MultiLocation {
74+
fn from(_: [Junction; 0]) -> Self {
75+
MultiLocation::Null
76+
}
77+
}
78+
79+
#from_tuples
80+
}
81+
}
82+
83+
fn generate_conversion_from_v1() -> TokenStream {
84+
let match_variants = (0..8u8)
85+
.map(|cur_num| {
86+
let variant = format_ident!("X{}", cur_num + 1);
87+
let idents = (1..=cur_num).map(|i| format_ident!("j{}", i)).collect::<Vec<_>>();
88+
89+
quote! {
90+
crate::v1::Junctions::#variant( j0 #(, #idents)* ) => res
91+
.pushed_with(Junction::from(j0))
92+
#( .and_then(|res| res.pushed_with(Junction::from(#idents))) )*
93+
.map_err(|_| ()),
94+
}
95+
})
96+
.collect::<TokenStream>();
97+
98+
quote! {
99+
impl TryFrom<crate::v1::MultiLocation> for MultiLocation {
100+
type Error = ();
101+
fn try_from(v1: crate::v1::MultiLocation) -> core::result::Result<Self, ()> {
102+
let mut res = MultiLocation::Null;
103+
104+
for _ in 0..v1.parents {
105+
res.push(Junction::Parent)?;
106+
}
107+
108+
match v1.interior {
109+
crate::v1::Junctions::Here => Ok(res),
110+
#match_variants
111+
}
112+
}
113+
}
114+
}
115+
}

xcm/procedural/src/v1.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2021 Parity Technologies (UK) Ltd.
2+
// This file is part of Polkadot.
3+
4+
// Polkadot is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
9+
// Polkadot is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
14+
// You should have received a copy of the GNU General Public License
15+
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
16+
17+
pub mod multilocation;

0 commit comments

Comments
 (0)