From 8feed6aedb3731766241611481bb29c2d2ef62d0 Mon Sep 17 00:00:00 2001 From: Keith Yeung <kungfukeith11@gmail.com> Date: Thu, 19 Aug 2021 02:24:55 -0700 Subject: [PATCH] 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 --- polkadot/Cargo.lock | 10 + polkadot/Cargo.toml | 1 + polkadot/xcm/Cargo.toml | 1 + polkadot/xcm/procedural/Cargo.toml | 13 + polkadot/xcm/procedural/src/lib.rs | 36 ++ polkadot/xcm/procedural/src/v0.rs | 17 + .../xcm/procedural/src/v0/multilocation.rs | 115 ++++ polkadot/xcm/procedural/src/v1.rs | 17 + .../xcm/procedural/src/v1/multilocation.rs | 204 +++++++ polkadot/xcm/src/v0/multi_location.rs | 203 +------ polkadot/xcm/src/v1/multilocation.rs | 516 ++---------------- 11 files changed, 486 insertions(+), 647 deletions(-) create mode 100644 polkadot/xcm/procedural/Cargo.toml create mode 100644 polkadot/xcm/procedural/src/lib.rs create mode 100644 polkadot/xcm/procedural/src/v0.rs create mode 100644 polkadot/xcm/procedural/src/v0/multilocation.rs create mode 100644 polkadot/xcm/procedural/src/v1.rs create mode 100644 polkadot/xcm/procedural/src/v1/multilocation.rs diff --git a/polkadot/Cargo.lock b/polkadot/Cargo.lock index 2d262c8e94e..fce796875ae 100644 --- a/polkadot/Cargo.lock +++ b/polkadot/Cargo.lock @@ -11775,6 +11775,7 @@ dependencies = [ "impl-trait-for-tuples", "log", "parity-scale-codec", + "xcm-procedural", ] [[package]] @@ -11835,6 +11836,15 @@ dependencies = [ "xcm-executor", ] +[[package]] +name = "xcm-procedural" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "xcm-simulator" version = "0.9.9" diff --git a/polkadot/Cargo.toml b/polkadot/Cargo.toml index ce6f8ddd1c5..3707b0b01c8 100644 --- a/polkadot/Cargo.toml +++ b/polkadot/Cargo.toml @@ -43,6 +43,7 @@ members = [ "xcm/xcm-simulator", "xcm/xcm-simulator/example", "xcm/pallet-xcm", + "xcm/procedural", "node/client", "node/collation-generation", "node/core/approval-voting", diff --git a/polkadot/xcm/Cargo.toml b/polkadot/xcm/Cargo.toml index a1bfa76130a..12b96a50216 100644 --- a/polkadot/xcm/Cargo.toml +++ b/polkadot/xcm/Cargo.toml @@ -10,6 +10,7 @@ impl-trait-for-tuples = "0.2.0" parity-scale-codec = { version = "2.0.0", default-features = false, features = [ "derive" ] } derivative = {version = "2.2.0", default-features = false, features = [ "use_core" ] } log = { version = "0.4.14", default-features = false } +xcm-procedural = { path = "procedural" } [features] default = ["std"] diff --git a/polkadot/xcm/procedural/Cargo.toml b/polkadot/xcm/procedural/Cargo.toml new file mode 100644 index 00000000000..914efad452a --- /dev/null +++ b/polkadot/xcm/procedural/Cargo.toml @@ -0,0 +1,13 @@ +[package] +authors = ["Parity Technologies <admin@parity.io>"] +name = "xcm-procedural" +version = "0.1.0" +edition = "2018" + +[lib] +proc-macro = true + +[dependencies] +proc-macro2 = "1.0.28" +quote = "1.0.9" +syn = "1.0.74" diff --git a/polkadot/xcm/procedural/src/lib.rs b/polkadot/xcm/procedural/src/lib.rs new file mode 100644 index 00000000000..fd6ffe55934 --- /dev/null +++ b/polkadot/xcm/procedural/src/lib.rs @@ -0,0 +1,36 @@ +// Copyright 2020 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>. + +//! Procedural macros used in XCM. + +use proc_macro::TokenStream; + +mod v0; +mod v1; + +#[proc_macro] +pub fn impl_conversion_functions_for_multilocation_v0(input: TokenStream) -> TokenStream { + v0::multilocation::generate_conversion_functions(input) + .unwrap_or_else(syn::Error::into_compile_error) + .into() +} + +#[proc_macro] +pub fn impl_conversion_functions_for_multilocation_v1(input: TokenStream) -> TokenStream { + v1::multilocation::generate_conversion_functions(input) + .unwrap_or_else(syn::Error::into_compile_error) + .into() +} diff --git a/polkadot/xcm/procedural/src/v0.rs b/polkadot/xcm/procedural/src/v0.rs new file mode 100644 index 00000000000..7774df4e9f8 --- /dev/null +++ b/polkadot/xcm/procedural/src/v0.rs @@ -0,0 +1,17 @@ +// Copyright 2021 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>. + +pub mod multilocation; diff --git a/polkadot/xcm/procedural/src/v0/multilocation.rs b/polkadot/xcm/procedural/src/v0/multilocation.rs new file mode 100644 index 00000000000..82db5cce4ee --- /dev/null +++ b/polkadot/xcm/procedural/src/v0/multilocation.rs @@ -0,0 +1,115 @@ +// Copyright 2021 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>. + +use proc_macro2::{Span, TokenStream}; +use quote::{format_ident, quote}; + +pub fn generate_conversion_functions(input: proc_macro::TokenStream) -> syn::Result<TokenStream> { + if !input.is_empty() { + return Err(syn::Error::new(Span::call_site(), "No arguments expected")) + } + + let from_tuples = generate_conversion_from_tuples(); + let from_v1 = generate_conversion_from_v1(); + + Ok(quote! { + #from_tuples + #from_v1 + }) +} + +fn generate_conversion_from_tuples() -> TokenStream { + let from_tuples = (0..8usize) + .map(|num_junctions| { + let junctions = + (0..=num_junctions).map(|_| format_ident!("Junction")).collect::<Vec<_>>(); + let idents = (0..=num_junctions).map(|i| format_ident!("j{}", i)).collect::<Vec<_>>(); + let variant = &format_ident!("X{}", num_junctions + 1); + let array_size = num_junctions + 1; + + quote! { + impl From<( #(#junctions,)* )> for MultiLocation { + fn from( ( #(#idents,)* ): ( #(#junctions,)* ) ) -> Self { + MultiLocation::#variant( #(#idents),* ) + } + } + + impl From<[Junction; #array_size]> for MultiLocation { + fn from(j: [Junction; #array_size]) -> Self { + let [#(#idents),*] = j; + MultiLocation::#variant( #(#idents),* ) + } + } + } + }) + .collect::<TokenStream>(); + + quote! { + impl From<()> for MultiLocation { + fn from(_: ()) -> Self { + MultiLocation::Null + } + } + + impl From<Junction> for MultiLocation { + fn from(x: Junction) -> Self { + MultiLocation::X1(x) + } + } + + impl From<[Junction; 0]> for MultiLocation { + fn from(_: [Junction; 0]) -> Self { + MultiLocation::Null + } + } + + #from_tuples + } +} + +fn generate_conversion_from_v1() -> TokenStream { + let match_variants = (0..8u8) + .map(|cur_num| { + let variant = format_ident!("X{}", cur_num + 1); + let idents = (1..=cur_num).map(|i| format_ident!("j{}", i)).collect::<Vec<_>>(); + + quote! { + crate::v1::Junctions::#variant( j0 #(, #idents)* ) => res + .pushed_with(Junction::from(j0)) + #( .and_then(|res| res.pushed_with(Junction::from(#idents))) )* + .map_err(|_| ()), + } + }) + .collect::<TokenStream>(); + + quote! { + impl TryFrom<crate::v1::MultiLocation> for MultiLocation { + type Error = (); + fn try_from(v1: crate::v1::MultiLocation) -> core::result::Result<Self, ()> { + let mut res = MultiLocation::Null; + + for _ in 0..v1.parents { + res.push(Junction::Parent)?; + } + + match v1.interior { + crate::v1::Junctions::Here => Ok(res), + #match_variants + } + } + } + } +} diff --git a/polkadot/xcm/procedural/src/v1.rs b/polkadot/xcm/procedural/src/v1.rs new file mode 100644 index 00000000000..7774df4e9f8 --- /dev/null +++ b/polkadot/xcm/procedural/src/v1.rs @@ -0,0 +1,17 @@ +// Copyright 2021 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>. + +pub mod multilocation; diff --git a/polkadot/xcm/procedural/src/v1/multilocation.rs b/polkadot/xcm/procedural/src/v1/multilocation.rs new file mode 100644 index 00000000000..c58f85ca31f --- /dev/null +++ b/polkadot/xcm/procedural/src/v1/multilocation.rs @@ -0,0 +1,204 @@ +// Copyright 2021 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>. + +use proc_macro2::{Span, TokenStream}; +use quote::{format_ident, quote}; +use syn::{Result, Token}; + +pub fn generate_conversion_functions(input: proc_macro::TokenStream) -> Result<TokenStream> { + if !input.is_empty() { + return Err(syn::Error::new(Span::call_site(), "No arguments expected")) + } + + // Support up to 8 Parents in a tuple, assuming that most use cases don't go past 8 parents. + let from_tuples = generate_conversion_from_tuples(8); + let from_v0 = generate_conversion_from_v0(); + + Ok(quote! { + #from_tuples + #from_v0 + }) +} + +fn generate_conversion_from_tuples(max_parents: u8) -> TokenStream { + let mut from_tuples = (0..8usize) + .map(|num_junctions| { + let junctions = + (0..=num_junctions).map(|_| format_ident!("Junction")).collect::<Vec<_>>(); + let idents = (0..=num_junctions).map(|i| format_ident!("j{}", i)).collect::<Vec<_>>(); + let variant = &format_ident!("X{}", num_junctions + 1); + let array_size = num_junctions + 1; + + let mut from_tuple = quote! { + impl From<( #(#junctions,)* )> for MultiLocation { + fn from( ( #(#idents,)* ): ( #(#junctions,)* ) ) -> Self { + MultiLocation { parents: 0, interior: Junctions::#variant( #(#idents),* ) } + } + } + + impl From<(u8, #(#junctions),*)> for MultiLocation { + fn from( ( parents, #(#idents),* ): (u8, #(#junctions),* ) ) -> Self { + MultiLocation { parents, interior: Junctions::#variant( #(#idents),* ) } + } + } + + impl From<(Ancestor, #(#junctions),*)> for MultiLocation { + fn from( ( Ancestor(parents), #(#idents),* ): (Ancestor, #(#junctions),* ) ) -> Self { + MultiLocation { parents, interior: Junctions::#variant( #(#idents),* ) } + } + } + + impl From<[Junction; #array_size]> for MultiLocation { + fn from(j: [Junction; #array_size]) -> Self { + let [#(#idents),*] = j; + MultiLocation { parents: 0, interior: Junctions::#variant( #(#idents),* ) } + } + } + }; + + let from_parent_tuples = (1..=max_parents).map(|cur_parents| { + let parents = (0..cur_parents).map(|_| format_ident!("Parent")).collect::<Vec<_>>(); + let underscores = + (0..cur_parents).map(|_| Token)).collect::<Vec<_>>(); + + quote! { + impl From<( #(#parents,)* #(#junctions),* )> for MultiLocation { + fn from( (#(#underscores,)* #(#idents),*): ( #(#parents,)* #(#junctions),* ) ) -> Self { + MultiLocation { parents: #cur_parents, interior: Junctions::#variant( #(#idents),* ) } + } + } + } + }); + + from_tuple.extend(from_parent_tuples); + from_tuple + }) + .collect::<TokenStream>(); + + let from_parent_junctions_tuples = (1..=max_parents).map(|cur_parents| { + let parents = (0..cur_parents).map(|_| format_ident!("Parent")).collect::<Vec<_>>(); + let underscores = + (0..cur_parents).map(|_| Token)).collect::<Vec<_>>(); + + quote! { + impl From<( #(#parents,)* Junctions )> for MultiLocation { + fn from( (#(#underscores,)* junctions): ( #(#parents,)* Junctions ) ) -> Self { + MultiLocation { parents: #cur_parents, interior: junctions } + } + } + } + }); + from_tuples.extend(from_parent_junctions_tuples); + + quote! { + impl From<Junctions> for MultiLocation { + fn from(junctions: Junctions) -> Self { + MultiLocation { parents: 0, interior: junctions } + } + } + + impl From<(u8, Junctions)> for MultiLocation { + fn from((parents, interior): (u8, Junctions)) -> Self { + MultiLocation { parents, interior } + } + } + + impl From<(Ancestor, Junctions)> for MultiLocation { + fn from((Ancestor(parents), interior): (Ancestor, Junctions)) -> Self { + MultiLocation { parents, interior } + } + } + + impl From<()> for MultiLocation { + fn from(_: ()) -> Self { + MultiLocation { parents: 0, interior: Junctions::Here } + } + } + + impl From<(u8,)> for MultiLocation { + fn from((parents,): (u8,)) -> Self { + MultiLocation { parents, interior: Junctions::Here } + } + } + + impl From<Junction> for MultiLocation { + fn from(x: Junction) -> Self { + MultiLocation { parents: 0, interior: Junctions::X1(x) } + } + } + + impl From<[Junction; 0]> for MultiLocation { + fn from(_: [Junction; 0]) -> Self { + MultiLocation { parents: 0, interior: Junctions::Here } + } + } + + #from_tuples + } +} + +fn generate_conversion_from_v0() -> TokenStream { + let match_variants = (0..8u8) + .map(|cur_num| { + let num_ancestors = cur_num + 1; + let variant = format_ident!("X{}", num_ancestors); + let idents = (0..=cur_num).map(|i| format_ident!("j{}", i)).collect::<Vec<_>>(); + + let intermediate_match_arms = (1..num_ancestors) + .rev() + .map(|parent_count| { + let parent_idents = + (0..parent_count).map(|j| format_ident!("j{}", j)).collect::<Vec<_>>(); + let junction_idents = (parent_count..num_ancestors) + .map(|j| format_ident!("j{}", j)) + .collect::<Vec<_>>(); + let junction_variant = format_ident!("X{}", num_ancestors - parent_count); + + quote! { + crate::v0::MultiLocation::#variant( #(#idents),* ) + if #( #parent_idents.is_parent() )&&* => + Ok(MultiLocation { + parents: #parent_count, + interior: #junction_variant( #( #junction_idents.try_into()? ),* ), + }), + } + }) + .collect::<TokenStream>(); + + quote! { + crate::v0::MultiLocation::#variant( #(#idents),* ) + if #( #idents.is_parent() )&&* => + Ok(MultiLocation::ancestor(#num_ancestors)), + #intermediate_match_arms + crate::v0::MultiLocation::#variant( #(#idents),* ) => + Ok( #variant( #( #idents.try_into()? ),* ).into() ), + } + }) + .collect::<TokenStream>(); + + quote! { + impl TryFrom<crate::v0::MultiLocation> for MultiLocation { + type Error = (); + fn try_from(v0: crate::v0::MultiLocation) -> core::result::Result<Self, ()> { + use Junctions::*; + match v0 { + crate::v0::MultiLocation::Null => Ok(Here.into()), + #match_variants + } + } + } + } +} diff --git a/polkadot/xcm/src/v0/multi_location.rs b/polkadot/xcm/src/v0/multi_location.rs index 89b10718647..1a6f4beb241 100644 --- a/polkadot/xcm/src/v0/multi_location.rs +++ b/polkadot/xcm/src/v0/multi_location.rs @@ -17,7 +17,6 @@ //! Cross-Consensus Message format data structures. use super::Junction; -use crate::v1::MultiLocation as MultiLocation1; use core::{convert::TryFrom, mem, result}; use parity_scale_codec::{self, Decode, Encode}; @@ -68,117 +67,7 @@ pub enum MultiLocation { /// Maximum number of junctions a `MultiLocation` can contain. pub const MAX_MULTILOCATION_LENGTH: usize = 8; -impl From<Junction> for MultiLocation { - fn from(x: Junction) -> Self { - MultiLocation::X1(x) - } -} - -impl From<()> for MultiLocation { - fn from(_: ()) -> Self { - MultiLocation::Null - } -} -impl From<(Junction,)> for MultiLocation { - fn from(x: (Junction,)) -> Self { - MultiLocation::X1(x.0) - } -} -impl From<(Junction, Junction)> for MultiLocation { - fn from(x: (Junction, Junction)) -> Self { - MultiLocation::X2(x.0, x.1) - } -} -impl From<(Junction, Junction, Junction)> for MultiLocation { - fn from(x: (Junction, Junction, Junction)) -> Self { - MultiLocation::X3(x.0, x.1, x.2) - } -} -impl From<(Junction, Junction, Junction, Junction)> for MultiLocation { - fn from(x: (Junction, Junction, Junction, Junction)) -> Self { - MultiLocation::X4(x.0, x.1, x.2, x.3) - } -} -impl From<(Junction, Junction, Junction, Junction, Junction)> for MultiLocation { - fn from(x: (Junction, Junction, Junction, Junction, Junction)) -> Self { - MultiLocation::X5(x.0, x.1, x.2, x.3, x.4) - } -} -impl From<(Junction, Junction, Junction, Junction, Junction, Junction)> for MultiLocation { - fn from(x: (Junction, Junction, Junction, Junction, Junction, Junction)) -> Self { - MultiLocation::X6(x.0, x.1, x.2, x.3, x.4, x.5) - } -} -impl From<(Junction, Junction, Junction, Junction, Junction, Junction, Junction)> - for MultiLocation -{ - fn from(x: (Junction, Junction, Junction, Junction, Junction, Junction, Junction)) -> Self { - MultiLocation::X7(x.0, x.1, x.2, x.3, x.4, x.5, x.6) - } -} -impl From<(Junction, Junction, Junction, Junction, Junction, Junction, Junction, Junction)> - for MultiLocation -{ - fn from( - x: (Junction, Junction, Junction, Junction, Junction, Junction, Junction, Junction), - ) -> Self { - MultiLocation::X8(x.0, x.1, x.2, x.3, x.4, x.5, x.6, x.7) - } -} - -impl From<[Junction; 0]> for MultiLocation { - fn from(_: [Junction; 0]) -> Self { - MultiLocation::Null - } -} -impl From<[Junction; 1]> for MultiLocation { - fn from(x: [Junction; 1]) -> Self { - let [x0] = x; - MultiLocation::X1(x0) - } -} -impl From<[Junction; 2]> for MultiLocation { - fn from(x: [Junction; 2]) -> Self { - let [x0, x1] = x; - MultiLocation::X2(x0, x1) - } -} -impl From<[Junction; 3]> for MultiLocation { - fn from(x: [Junction; 3]) -> Self { - let [x0, x1, x2] = x; - MultiLocation::X3(x0, x1, x2) - } -} -impl From<[Junction; 4]> for MultiLocation { - fn from(x: [Junction; 4]) -> Self { - let [x0, x1, x2, x3] = x; - MultiLocation::X4(x0, x1, x2, x3) - } -} -impl From<[Junction; 5]> for MultiLocation { - fn from(x: [Junction; 5]) -> Self { - let [x0, x1, x2, x3, x4] = x; - MultiLocation::X5(x0, x1, x2, x3, x4) - } -} -impl From<[Junction; 6]> for MultiLocation { - fn from(x: [Junction; 6]) -> Self { - let [x0, x1, x2, x3, x4, x5] = x; - MultiLocation::X6(x0, x1, x2, x3, x4, x5) - } -} -impl From<[Junction; 7]> for MultiLocation { - fn from(x: [Junction; 7]) -> Self { - let [x0, x1, x2, x3, x4, x5, x6] = x; - MultiLocation::X7(x0, x1, x2, x3, x4, x5, x6) - } -} -impl From<[Junction; 8]> for MultiLocation { - fn from(x: [Junction; 8]) -> Self { - let [x0, x1, x2, x3, x4, x5, x6, x7] = x; - MultiLocation::X8(x0, x1, x2, x3, x4, x5, x6, x7) - } -} +xcm_procedural::impl_conversion_functions_for_multilocation_v0!(); pub struct MultiLocationIterator(MultiLocation); impl Iterator for MultiLocationIterator { @@ -696,75 +585,9 @@ impl MultiLocation { } } -impl TryFrom<MultiLocation1> for MultiLocation { - type Error = (); - fn try_from(v1: MultiLocation1) -> result::Result<Self, ()> { - use crate::v1::Junctions::*; - let mut res = Self::Null; - - for _ in 0..v1.parents { - res.push(Junction::Parent)?; - } - - match v1.interior { - Here => Ok(res), - X1(j0) => res.pushed_with(Junction::from(j0)).map_err(|_| ()), - X2(j0, j1) => res - .pushed_with(Junction::from(j0)) - .and_then(|res| res.pushed_with(Junction::from(j1))) - .map_err(|_| ()), - X3(j0, j1, j2) => res - .pushed_with(Junction::from(j0)) - .and_then(|res| res.pushed_with(Junction::from(j1))) - .and_then(|res| res.pushed_with(Junction::from(j2))) - .map_err(|_| ()), - X4(j0, j1, j2, j3) => res - .pushed_with(Junction::from(j0)) - .and_then(|res| res.pushed_with(Junction::from(j1))) - .and_then(|res| res.pushed_with(Junction::from(j2))) - .and_then(|res| res.pushed_with(Junction::from(j3))) - .map_err(|_| ()), - X5(j0, j1, j2, j3, j4) => res - .pushed_with(Junction::from(j0)) - .and_then(|res| res.pushed_with(Junction::from(j1))) - .and_then(|res| res.pushed_with(Junction::from(j2))) - .and_then(|res| res.pushed_with(Junction::from(j3))) - .and_then(|res| res.pushed_with(Junction::from(j4))) - .map_err(|_| ()), - X6(j0, j1, j2, j3, j4, j5) => res - .pushed_with(Junction::from(j0)) - .and_then(|res| res.pushed_with(Junction::from(j1))) - .and_then(|res| res.pushed_with(Junction::from(j2))) - .and_then(|res| res.pushed_with(Junction::from(j3))) - .and_then(|res| res.pushed_with(Junction::from(j4))) - .and_then(|res| res.pushed_with(Junction::from(j5))) - .map_err(|_| ()), - X7(j0, j1, j2, j3, j4, j5, j6) => res - .pushed_with(Junction::from(j0)) - .and_then(|res| res.pushed_with(Junction::from(j1))) - .and_then(|res| res.pushed_with(Junction::from(j2))) - .and_then(|res| res.pushed_with(Junction::from(j3))) - .and_then(|res| res.pushed_with(Junction::from(j4))) - .and_then(|res| res.pushed_with(Junction::from(j5))) - .and_then(|res| res.pushed_with(Junction::from(j6))) - .map_err(|_| ()), - X8(j0, j1, j2, j3, j4, j5, j6, j7) => res - .pushed_with(Junction::from(j0)) - .and_then(|res| res.pushed_with(Junction::from(j1))) - .and_then(|res| res.pushed_with(Junction::from(j2))) - .and_then(|res| res.pushed_with(Junction::from(j3))) - .and_then(|res| res.pushed_with(Junction::from(j4))) - .and_then(|res| res.pushed_with(Junction::from(j5))) - .and_then(|res| res.pushed_with(Junction::from(j6))) - .and_then(|res| res.pushed_with(Junction::from(j7))) - .map_err(|_| ()), - } - } -} - #[cfg(test)] mod tests { - use super::MultiLocation::*; + use super::MultiLocation::{self, *}; use crate::opaque::v0::{Junction::*, NetworkId::Any}; #[test] @@ -867,4 +690,26 @@ mod tests { m.canonicalize(); assert_eq!(m, X4(Parent, Parent, Parachain(1), Parachain(2))); } + + #[test] + fn conversion_from_other_types_works() { + use crate::v1::{self, Junction, Junctions}; + use core::convert::TryInto; + + fn takes_multilocation<Arg: Into<MultiLocation>>(_arg: Arg) {} + + takes_multilocation(Null); + takes_multilocation(Parent); + takes_multilocation([Parent, Parachain(4)]); + + assert_eq!(v1::MultiLocation::here().try_into(), Ok(MultiLocation::Null)); + assert_eq!( + v1::MultiLocation::new(1, Junctions::X1(Junction::Parachain(8))).try_into(), + Ok(X2(Parent, Parachain(8))), + ); + assert_eq!( + v1::MultiLocation::new(24, Junctions::Here).try_into(), + Err::<MultiLocation, ()>(()), + ); + } } diff --git a/polkadot/xcm/src/v1/multilocation.rs b/polkadot/xcm/src/v1/multilocation.rs index b90c5489273..d702422b6d0 100644 --- a/polkadot/xcm/src/v1/multilocation.rs +++ b/polkadot/xcm/src/v1/multilocation.rs @@ -17,7 +17,6 @@ //! Cross-Consensus Message format data structures. use super::Junction; -use crate::v0::MultiLocation as MultiLocation0; use core::{ convert::{TryFrom, TryInto}, mem, result, @@ -315,6 +314,7 @@ impl MultiLocation { } /// A unit struct which can be converted into a `MultiLocation` of `parents` value 1. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)] pub struct Parent; impl From<Parent> for MultiLocation { fn from(_: Parent) -> Self { @@ -323,6 +323,7 @@ impl From<Parent> for MultiLocation { } /// A tuple struct which can be converted into a `MultiLocation` of `parents` value 1 with the inner interior. +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] pub struct ParentThen(Junctions); impl From<ParentThen> for MultiLocation { fn from(x: ParentThen) -> Self { @@ -331,6 +332,7 @@ impl From<ParentThen> for MultiLocation { } /// A unit struct which can be converted into a `MultiLocation` of the inner `parents` value. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)] pub struct Ancestor(u8); impl From<Ancestor> for MultiLocation { fn from(x: Ancestor) -> Self { @@ -339,6 +341,7 @@ impl From<Ancestor> for MultiLocation { } /// A unit struct which can be converted into a `MultiLocation` of the inner `parents` value and the inner interior. +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] pub struct AncestorThen(u8, Junctions); impl From<AncestorThen> for MultiLocation { fn from(x: AncestorThen) -> Self { @@ -346,217 +349,7 @@ impl From<AncestorThen> for MultiLocation { } } -impl From<Junctions> for MultiLocation { - fn from(junctions: Junctions) -> Self { - MultiLocation { parents: 0, interior: junctions } - } -} - -impl From<(u8, Junctions)> for MultiLocation { - fn from((parents, interior): (u8, Junctions)) -> Self { - MultiLocation { parents, interior } - } -} - -impl From<Junction> for MultiLocation { - fn from(x: Junction) -> Self { - MultiLocation { parents: 0, interior: Junctions::X1(x) } - } -} - -impl From<()> for MultiLocation { - fn from(_: ()) -> Self { - MultiLocation { parents: 0, interior: Junctions::Here } - } -} -impl From<(Junction,)> for MultiLocation { - fn from(x: (Junction,)) -> Self { - MultiLocation { parents: 0, interior: Junctions::X1(x.0) } - } -} -impl From<(Junction, Junction)> for MultiLocation { - fn from(x: (Junction, Junction)) -> Self { - MultiLocation { parents: 0, interior: Junctions::X2(x.0, x.1) } - } -} -impl From<(Junction, Junction, Junction)> for MultiLocation { - fn from(x: (Junction, Junction, Junction)) -> Self { - MultiLocation { parents: 0, interior: Junctions::X3(x.0, x.1, x.2) } - } -} -impl From<(Junction, Junction, Junction, Junction)> for MultiLocation { - fn from(x: (Junction, Junction, Junction, Junction)) -> Self { - MultiLocation { parents: 0, interior: Junctions::X4(x.0, x.1, x.2, x.3) } - } -} -impl From<(Junction, Junction, Junction, Junction, Junction)> for MultiLocation { - fn from(x: (Junction, Junction, Junction, Junction, Junction)) -> Self { - MultiLocation { parents: 0, interior: Junctions::X5(x.0, x.1, x.2, x.3, x.4) } - } -} -impl From<(Junction, Junction, Junction, Junction, Junction, Junction)> for MultiLocation { - fn from(x: (Junction, Junction, Junction, Junction, Junction, Junction)) -> Self { - MultiLocation { parents: 0, interior: Junctions::X6(x.0, x.1, x.2, x.3, x.4, x.5) } - } -} -impl From<(Junction, Junction, Junction, Junction, Junction, Junction, Junction)> - for MultiLocation -{ - fn from(x: (Junction, Junction, Junction, Junction, Junction, Junction, Junction)) -> Self { - MultiLocation { parents: 0, interior: Junctions::X7(x.0, x.1, x.2, x.3, x.4, x.5, x.6) } - } -} -impl From<(Junction, Junction, Junction, Junction, Junction, Junction, Junction, Junction)> - for MultiLocation -{ - fn from( - x: (Junction, Junction, Junction, Junction, Junction, Junction, Junction, Junction), - ) -> Self { - MultiLocation { - parents: 0, - interior: Junctions::X8(x.0, x.1, x.2, x.3, x.4, x.5, x.6, x.7), - } - } -} - -impl From<(u8,)> for MultiLocation { - fn from((parents,): (u8,)) -> Self { - MultiLocation { parents, interior: Junctions::Here } - } -} -impl From<(u8, Junction)> for MultiLocation { - fn from((parents, j0): (u8, Junction)) -> Self { - MultiLocation { parents, interior: Junctions::X1(j0) } - } -} -impl From<(u8, Junction, Junction)> for MultiLocation { - fn from((parents, j0, j1): (u8, Junction, Junction)) -> Self { - MultiLocation { parents, interior: Junctions::X2(j0, j1) } - } -} -impl From<(u8, Junction, Junction, Junction)> for MultiLocation { - fn from((parents, j0, j1, j2): (u8, Junction, Junction, Junction)) -> Self { - MultiLocation { parents, interior: Junctions::X3(j0, j1, j2) } - } -} -impl From<(u8, Junction, Junction, Junction, Junction)> for MultiLocation { - fn from((parents, j0, j1, j2, j3): (u8, Junction, Junction, Junction, Junction)) -> Self { - MultiLocation { parents, interior: Junctions::X4(j0, j1, j2, j3) } - } -} -impl From<(u8, Junction, Junction, Junction, Junction, Junction)> for MultiLocation { - fn from( - (parents, j0, j1, j2, j3, j4): (u8, Junction, Junction, Junction, Junction, Junction), - ) -> Self { - MultiLocation { parents, interior: Junctions::X5(j0, j1, j2, j3, j4) } - } -} -impl From<(u8, Junction, Junction, Junction, Junction, Junction, Junction)> for MultiLocation { - fn from( - (parents, j0, j1, j2, j3, j4, j5): ( - u8, - Junction, - Junction, - Junction, - Junction, - Junction, - Junction, - ), - ) -> Self { - MultiLocation { parents, interior: Junctions::X6(j0, j1, j2, j3, j4, j5) } - } -} -impl From<(u8, Junction, Junction, Junction, Junction, Junction, Junction, Junction)> - for MultiLocation -{ - fn from( - (parents, j0, j1, j2, j3, j4, j5, j6): ( - u8, - Junction, - Junction, - Junction, - Junction, - Junction, - Junction, - Junction, - ), - ) -> Self { - MultiLocation { parents, interior: Junctions::X7(j0, j1, j2, j3, j4, j5, j6) } - } -} -impl From<(u8, Junction, Junction, Junction, Junction, Junction, Junction, Junction, Junction)> - for MultiLocation -{ - fn from( - (parents, j0, j1, j2, j3, j4, j5, j6, j7): ( - u8, - Junction, - Junction, - Junction, - Junction, - Junction, - Junction, - Junction, - Junction, - ), - ) -> Self { - MultiLocation { parents, interior: Junctions::X8(j0, j1, j2, j3, j4, j5, j6, j7) } - } -} - -impl From<[Junction; 0]> for MultiLocation { - fn from(_: [Junction; 0]) -> Self { - MultiLocation { parents: 0, interior: Junctions::Here } - } -} -impl From<[Junction; 1]> for MultiLocation { - fn from(x: [Junction; 1]) -> Self { - let [x0] = x; - MultiLocation { parents: 0, interior: Junctions::X1(x0) } - } -} -impl From<[Junction; 2]> for MultiLocation { - fn from(x: [Junction; 2]) -> Self { - let [x0, x1] = x; - MultiLocation { parents: 0, interior: Junctions::X2(x0, x1) } - } -} -impl From<[Junction; 3]> for MultiLocation { - fn from(x: [Junction; 3]) -> Self { - let [x0, x1, x2] = x; - MultiLocation { parents: 0, interior: Junctions::X3(x0, x1, x2) } - } -} -impl From<[Junction; 4]> for MultiLocation { - fn from(x: [Junction; 4]) -> Self { - let [x0, x1, x2, x3] = x; - MultiLocation { parents: 0, interior: Junctions::X4(x0, x1, x2, x3) } - } -} -impl From<[Junction; 5]> for MultiLocation { - fn from(x: [Junction; 5]) -> Self { - let [x0, x1, x2, x3, x4] = x; - MultiLocation { parents: 0, interior: Junctions::X5(x0, x1, x2, x3, x4) } - } -} -impl From<[Junction; 6]> for MultiLocation { - fn from(x: [Junction; 6]) -> Self { - let [x0, x1, x2, x3, x4, x5] = x; - MultiLocation { parents: 0, interior: Junctions::X6(x0, x1, x2, x3, x4, x5) } - } -} -impl From<[Junction; 7]> for MultiLocation { - fn from(x: [Junction; 7]) -> Self { - let [x0, x1, x2, x3, x4, x5, x6] = x; - MultiLocation { parents: 0, interior: Junctions::X7(x0, x1, x2, x3, x4, x5, x6) } - } -} -impl From<[Junction; 8]> for MultiLocation { - fn from(x: [Junction; 8]) -> Self { - let [x0, x1, x2, x3, x4, x5, x6, x7] = x; - MultiLocation { parents: 0, interior: Junctions::X8(x0, x1, x2, x3, x4, x5, x6, x7) } - } -} +xcm_procedural::impl_conversion_functions_for_multilocation_v1!(); /// Maximum number of `Junction`s that a `Junctions` can contain. const MAX_JUNCTIONS: usize = 8; @@ -965,264 +758,9 @@ impl TryFrom<MultiLocation> for Junctions { } } -impl TryFrom<MultiLocation0> for MultiLocation { - type Error = (); - fn try_from(old: MultiLocation0) -> result::Result<Self, ()> { - use Junctions::*; - match old { - MultiLocation0::Null => Ok(Here.into()), - MultiLocation0::X1(j0) if j0.is_parent() => Ok(Parent.into()), - MultiLocation0::X1(j0) => Ok(X1(j0.try_into()?).into()), - MultiLocation0::X2(j0, j1) if j0.is_parent() && j1.is_parent() => - Ok(MultiLocation::grandparent()), - MultiLocation0::X2(j0, j1) if j0.is_parent() => - Ok(MultiLocation { parents: 1, interior: X1(j1.try_into()?) }), - MultiLocation0::X2(j0, j1) => Ok(X2(j0.try_into()?, j1.try_into()?).into()), - MultiLocation0::X3(j0, j1, j2) - if j0.is_parent() && j1.is_parent() && j2.is_parent() => - Ok(MultiLocation::ancestor(3)), - MultiLocation0::X3(j0, j1, j2) if j0.is_parent() && j1.is_parent() => - Ok(MultiLocation { parents: 2, interior: X1(j2.try_into()?) }), - MultiLocation0::X3(j0, j1, j2) if j0.is_parent() => - Ok(MultiLocation { parents: 1, interior: X2(j1.try_into()?, j2.try_into()?) }), - MultiLocation0::X3(j0, j1, j2) => - Ok(X3(j0.try_into()?, j1.try_into()?, j2.try_into()?).into()), - MultiLocation0::X4(j0, j1, j2, j3) - if j0.is_parent() && j1.is_parent() && j2.is_parent() && j3.is_parent() => - Ok(MultiLocation::ancestor(4)), - MultiLocation0::X4(j0, j1, j2, j3) - if j0.is_parent() && j1.is_parent() && j2.is_parent() => - Ok(MultiLocation { parents: 3, interior: X1(j3.try_into()?) }), - MultiLocation0::X4(j0, j1, j2, j3) if j0.is_parent() && j1.is_parent() => - Ok(MultiLocation { parents: 2, interior: X2(j2.try_into()?, j3.try_into()?) }), - MultiLocation0::X4(j0, j1, j2, j3) if j0.is_parent() => Ok(MultiLocation { - parents: 1, - interior: X3(j1.try_into()?, j2.try_into()?, j3.try_into()?), - }), - MultiLocation0::X4(j0, j1, j2, j3) => - Ok(X4(j0.try_into()?, j1.try_into()?, j2.try_into()?, j3.try_into()?).into()), - MultiLocation0::X5(j0, j1, j2, j3, j4) - if j0.is_parent() && - j1.is_parent() && j2.is_parent() && - j3.is_parent() && j4.is_parent() => - Ok(MultiLocation::ancestor(5)), - MultiLocation0::X5(j0, j1, j2, j3, j4) - if j0.is_parent() && j1.is_parent() && j2.is_parent() && j3.is_parent() => - Ok(MultiLocation { parents: 4, interior: X1(j4.try_into()?) }), - MultiLocation0::X5(j0, j1, j2, j3, j4) - if j0.is_parent() && j1.is_parent() && j2.is_parent() => - Ok(MultiLocation { parents: 3, interior: X2(j3.try_into()?, j4.try_into()?) }), - MultiLocation0::X5(j0, j1, j2, j3, j4) if j0.is_parent() && j1.is_parent() => - Ok(MultiLocation { - parents: 2, - interior: X3(j2.try_into()?, j3.try_into()?, j4.try_into()?), - }), - MultiLocation0::X5(j0, j1, j2, j3, j4) if j0.is_parent() => Ok(MultiLocation { - parents: 1, - interior: X4(j1.try_into()?, j2.try_into()?, j3.try_into()?, j4.try_into()?), - }), - MultiLocation0::X5(j0, j1, j2, j3, j4) => Ok(X5( - j0.try_into()?, - j1.try_into()?, - j2.try_into()?, - j3.try_into()?, - j4.try_into()?, - ) - .into()), - MultiLocation0::X6(j0, j1, j2, j3, j4, j5) - if j0.is_parent() && - j1.is_parent() && j2.is_parent() && - j3.is_parent() && j4.is_parent() && - j5.is_parent() => - Ok(MultiLocation::ancestor(6)), - MultiLocation0::X6(j0, j1, j2, j3, j4, j5) - if j0.is_parent() && - j1.is_parent() && j2.is_parent() && - j3.is_parent() && j4.is_parent() => - Ok(MultiLocation { parents: 5, interior: X1(j5.try_into()?) }), - MultiLocation0::X6(j0, j1, j2, j3, j4, j5) - if j0.is_parent() && j1.is_parent() && j2.is_parent() && j3.is_parent() => - Ok(MultiLocation { parents: 4, interior: X2(j4.try_into()?, j5.try_into()?) }), - MultiLocation0::X6(j0, j1, j2, j3, j4, j5) - if j0.is_parent() && j1.is_parent() && j2.is_parent() => - Ok(MultiLocation { - parents: 3, - interior: X3(j3.try_into()?, j4.try_into()?, j5.try_into()?), - }), - MultiLocation0::X6(j0, j1, j2, j3, j4, j5) if j0.is_parent() && j1.is_parent() => - Ok(MultiLocation { - parents: 2, - interior: X4(j2.try_into()?, j3.try_into()?, j4.try_into()?, j5.try_into()?), - }), - MultiLocation0::X6(j0, j1, j2, j3, j4, j5) if j0.is_parent() => Ok(MultiLocation { - parents: 1, - interior: X5( - j1.try_into()?, - j2.try_into()?, - j3.try_into()?, - j4.try_into()?, - j5.try_into()?, - ), - }), - MultiLocation0::X6(j0, j1, j2, j3, j4, j5) => Ok(X6( - j0.try_into()?, - j1.try_into()?, - j2.try_into()?, - j3.try_into()?, - j4.try_into()?, - j5.try_into()?, - ) - .into()), - MultiLocation0::X7(j0, j1, j2, j3, j4, j5, j6) - if j0.is_parent() && - j1.is_parent() && j2.is_parent() && - j3.is_parent() && j4.is_parent() && - j5.is_parent() && j6.is_parent() => - Ok(MultiLocation::ancestor(7)), - MultiLocation0::X7(j0, j1, j2, j3, j4, j5, j6) - if j0.is_parent() && - j1.is_parent() && j2.is_parent() && - j3.is_parent() && j4.is_parent() && - j5.is_parent() => - Ok(MultiLocation { parents: 6, interior: X1(j6.try_into()?) }), - MultiLocation0::X7(j0, j1, j2, j3, j4, j5, j6) - if j0.is_parent() && - j1.is_parent() && j2.is_parent() && - j3.is_parent() && j4.is_parent() => - Ok(MultiLocation { parents: 5, interior: X2(j5.try_into()?, j6.try_into()?) }), - MultiLocation0::X7(j0, j1, j2, j3, j4, j5, j6) - if j0.is_parent() && j1.is_parent() && j2.is_parent() && j3.is_parent() => - Ok(MultiLocation { - parents: 4, - interior: X3(j4.try_into()?, j5.try_into()?, j6.try_into()?), - }), - MultiLocation0::X7(j0, j1, j2, j3, j4, j5, j6) - if j0.is_parent() && j1.is_parent() && j2.is_parent() => - Ok(MultiLocation { - parents: 3, - interior: X4(j3.try_into()?, j4.try_into()?, j5.try_into()?, j6.try_into()?), - }), - MultiLocation0::X7(j0, j1, j2, j3, j4, j5, j6) if j0.is_parent() && j1.is_parent() => - Ok(MultiLocation { - parents: 2, - interior: X5( - j2.try_into()?, - j3.try_into()?, - j4.try_into()?, - j5.try_into()?, - j6.try_into()?, - ), - }), - MultiLocation0::X7(j0, j1, j2, j3, j4, j5, j6) if j0.is_parent() => Ok(MultiLocation { - parents: 1, - interior: X6( - j1.try_into()?, - j2.try_into()?, - j3.try_into()?, - j4.try_into()?, - j5.try_into()?, - j6.try_into()?, - ), - }), - MultiLocation0::X7(j0, j1, j2, j3, j4, j5, j6) => Ok(X7( - j0.try_into()?, - j1.try_into()?, - j2.try_into()?, - j3.try_into()?, - j4.try_into()?, - j5.try_into()?, - j6.try_into()?, - ) - .into()), - MultiLocation0::X8(j0, j1, j2, j3, j4, j5, j6, j7) - if j0.is_parent() && - j1.is_parent() && j2.is_parent() && - j3.is_parent() && j4.is_parent() && - j5.is_parent() && j6.is_parent() && - j7.is_parent() => - Ok(MultiLocation::ancestor(8)), - MultiLocation0::X8(j0, j1, j2, j3, j4, j5, j6, j7) - if j0.is_parent() && - j1.is_parent() && j2.is_parent() && - j3.is_parent() && j4.is_parent() && - j5.is_parent() && j6.is_parent() => - Ok(MultiLocation { parents: 7, interior: X1(j7.try_into()?) }), - MultiLocation0::X8(j0, j1, j2, j3, j4, j5, j6, j7) - if j0.is_parent() && - j1.is_parent() && j2.is_parent() && - j3.is_parent() && j4.is_parent() && - j5.is_parent() => - Ok(MultiLocation { parents: 6, interior: X2(j6.try_into()?, j7.try_into()?) }), - MultiLocation0::X8(j0, j1, j2, j3, j4, j5, j6, j7) - if j0.is_parent() && - j1.is_parent() && j2.is_parent() && - j3.is_parent() && j4.is_parent() => - Ok(MultiLocation { - parents: 5, - interior: X3(j5.try_into()?, j6.try_into()?, j7.try_into()?), - }), - MultiLocation0::X8(j0, j1, j2, j3, j4, j5, j6, j7) - if j0.is_parent() && j1.is_parent() && j2.is_parent() && j3.is_parent() => - Ok(MultiLocation { - parents: 4, - interior: X4(j4.try_into()?, j5.try_into()?, j6.try_into()?, j7.try_into()?), - }), - MultiLocation0::X8(j0, j1, j2, j3, j4, j5, j6, j7) - if j0.is_parent() && j1.is_parent() && j2.is_parent() => - Ok(MultiLocation { - parents: 3, - interior: X5( - j3.try_into()?, - j4.try_into()?, - j5.try_into()?, - j6.try_into()?, - j7.try_into()?, - ), - }), - MultiLocation0::X8(j0, j1, j2, j3, j4, j5, j6, j7) - if j0.is_parent() && j1.is_parent() => - Ok(MultiLocation { - parents: 2, - interior: X6( - j2.try_into()?, - j3.try_into()?, - j4.try_into()?, - j5.try_into()?, - j6.try_into()?, - j7.try_into()?, - ), - }), - MultiLocation0::X8(j0, j1, j2, j3, j4, j5, j6, j7) if j0.is_parent() => - Ok(MultiLocation { - parents: 1, - interior: X7( - j1.try_into()?, - j2.try_into()?, - j3.try_into()?, - j4.try_into()?, - j5.try_into()?, - j6.try_into()?, - j7.try_into()?, - ), - }), - MultiLocation0::X8(j0, j1, j2, j3, j4, j5, j6, j7) => Ok(X8( - j0.try_into()?, - j1.try_into()?, - j2.try_into()?, - j3.try_into()?, - j4.try_into()?, - j5.try_into()?, - j6.try_into()?, - j7.try_into()?, - ) - .into()), - } - } -} - #[cfg(test)] mod tests { - use super::{Junctions::*, MultiLocation}; + use super::{Ancestor, AncestorThen, Junctions::*, MultiLocation, Parent, ParentThen}; use crate::opaque::v1::{Junction::*, NetworkId::Any}; use parity_scale_codec::{Decode, Encode}; @@ -1330,4 +868,46 @@ mod tests { assert_eq!(iter.next(), None); assert_eq!(iter.next_back(), None); } + + #[test] + fn conversion_from_other_types_works() { + use crate::v0; + use core::convert::TryInto; + + fn takes_multilocation<Arg: Into<MultiLocation>>(_arg: Arg) {} + + takes_multilocation(Parent); + takes_multilocation(Here); + takes_multilocation(X1(Parachain(42))); + takes_multilocation((255, PalletInstance(8))); + takes_multilocation((Ancestor(5), Parachain(1), PalletInstance(3))); + takes_multilocation((Ancestor(2), Here)); + takes_multilocation(AncestorThen( + 3, + X2(Parachain(43), AccountIndex64 { network: Any, index: 155 }), + )); + takes_multilocation((Parent, AccountId32 { network: Any, id: [0; 32] })); + takes_multilocation((Parent, Here)); + takes_multilocation(ParentThen(X1(Parachain(75)))); + takes_multilocation([Parachain(100), PalletInstance(3)]); + + assert_eq!(v0::MultiLocation::Null.try_into(), Ok(MultiLocation::here())); + assert_eq!( + v0::MultiLocation::X1(v0::Junction::Parent).try_into(), + Ok(MultiLocation::parent()) + ); + assert_eq!( + v0::MultiLocation::X2(v0::Junction::Parachain(88), v0::Junction::Parent).try_into(), + Err::<MultiLocation, ()>(()), + ); + assert_eq!( + v0::MultiLocation::X3( + v0::Junction::Parent, + v0::Junction::Parent, + v0::Junction::GeneralKey(b"foo".to_vec()), + ) + .try_into(), + Ok(MultiLocation { parents: 2, interior: X1(GeneralKey(b"foo".to_vec())) }), + ); + } } -- GitLab