1
// Copyright (C) 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
//! Cross-Consensus Message format data structures.
18

            
19
use super::Junction;
20
use crate::v3::MultiLocation as NewMultiLocation;
21
use codec::{Decode, Encode, MaxEncodedLen};
22
use core::{mem, result};
23
use scale_info::TypeInfo;
24

            
25
/// A relative path between state-bearing consensus systems.
26
///
27
/// A location in a consensus system is defined as an *isolatable state machine* held within global
28
/// consensus. The location in question need not have a sophisticated consensus algorithm of its
29
/// own; a single account within Ethereum, for example, could be considered a location.
30
///
31
/// A very-much non-exhaustive list of types of location include:
32
/// - A (normal, layer-1) block chain, e.g. the Bitcoin mainnet or a parachain.
33
/// - A layer-0 super-chain, e.g. the Polkadot Relay chain.
34
/// - A layer-2 smart contract, e.g. an ERC-20 on Ethereum.
35
/// - A logical functional component of a chain, e.g. a single instance of a pallet on a Frame-based
36
///   Substrate chain.
37
/// - An account.
38
///
39
/// A `MultiLocation` is a *relative identifier*, meaning that it can only be used to define the
40
/// relative path between two locations, and cannot generally be used to refer to a location
41
/// universally. It is comprised of an integer number of parents specifying the number of times to
42
/// "escape" upwards into the containing consensus system and then a number of *junctions*, each
43
/// diving down and specifying some interior portion of state (which may be considered a
44
/// "sub-consensus" system).
45
///
46
/// This specific `MultiLocation` implementation uses a `Junctions` datatype which is a Rust `enum`
47
/// in order to make pattern matching easier. There are occasions where it is important to ensure
48
/// that a value is strictly an interior location, in those cases, `Junctions` may be used.
49
///
50
/// The `MultiLocation` value of `Null` simply refers to the interpreting consensus system.
51
#[derive(Clone, Decode, Encode, Eq, PartialEq, Ord, PartialOrd, Debug, TypeInfo, MaxEncodedLen)]
52
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
53
#[scale_info(replace_segment("staging_xcm", "xcm"))]
54
pub struct MultiLocation {
55
	/// The number of parent junctions at the beginning of this `MultiLocation`.
56
	pub parents: u8,
57
	/// The interior (i.e. non-parent) junctions that this `MultiLocation` contains.
58
	pub interior: Junctions,
59
}
60

            
61
impl Default for MultiLocation {
62
	fn default() -> Self {
63
		Self { parents: 0, interior: Junctions::Here }
64
	}
65
}
66

            
67
/// A relative location which is constrained to be an interior location of the context.
68
///
69
/// See also `MultiLocation`.
70
pub type InteriorMultiLocation = Junctions;
71

            
72
impl MultiLocation {
73
	/// Creates a new `MultiLocation` with the given number of parents and interior junctions.
74
	pub fn new(parents: u8, junctions: Junctions) -> MultiLocation {
75
		MultiLocation { parents, interior: junctions }
76
	}
77

            
78
	/// Consume `self` and return the equivalent `VersionedLocation` value.
79
	pub fn versioned(self) -> crate::VersionedLocation {
80
		self.into()
81
	}
82

            
83
	/// Creates a new `MultiLocation` with 0 parents and a `Here` interior.
84
	///
85
	/// The resulting `MultiLocation` can be interpreted as the "current consensus system".
86
	pub const fn here() -> MultiLocation {
87
		MultiLocation { parents: 0, interior: Junctions::Here }
88
	}
89

            
90
	/// Creates a new `MultiLocation` which evaluates to the parent context.
91
	pub const fn parent() -> MultiLocation {
92
		MultiLocation { parents: 1, interior: Junctions::Here }
93
	}
94

            
95
	/// Creates a new `MultiLocation` which evaluates to the grand parent context.
96
	pub const fn grandparent() -> MultiLocation {
97
		MultiLocation { parents: 2, interior: Junctions::Here }
98
	}
99

            
100
	/// Creates a new `MultiLocation` with `parents` and an empty (`Here`) interior.
101
	pub const fn ancestor(parents: u8) -> MultiLocation {
102
		MultiLocation { parents, interior: Junctions::Here }
103
	}
104

            
105
	/// Whether the `MultiLocation` has no parents and has a `Here` interior.
106
	pub const fn is_here(&self) -> bool {
107
		self.parents == 0 && self.interior.len() == 0
108
	}
109

            
110
	/// Return a reference to the interior field.
111
	pub fn interior(&self) -> &Junctions {
112
		&self.interior
113
	}
114

            
115
	/// Return a mutable reference to the interior field.
116
	pub fn interior_mut(&mut self) -> &mut Junctions {
117
		&mut self.interior
118
	}
119

            
120
	/// Returns the number of `Parent` junctions at the beginning of `self`.
121
	pub const fn parent_count(&self) -> u8 {
122
		self.parents
123
	}
124

            
125
	/// Returns boolean indicating whether `self` contains only the specified amount of
126
	/// parents and no interior junctions.
127
	pub const fn contains_parents_only(&self, count: u8) -> bool {
128
		matches!(self.interior, Junctions::Here) && self.parents == count
129
	}
130

            
131
	/// Returns the number of parents and junctions in `self`.
132
	pub const fn len(&self) -> usize {
133
		self.parent_count() as usize + self.interior.len()
134
	}
135

            
136
	/// Returns the first interior junction, or `None` if the location is empty or contains only
137
	/// parents.
138
	pub fn first_interior(&self) -> Option<&Junction> {
139
		self.interior.first()
140
	}
141

            
142
	/// Returns last junction, or `None` if the location is empty or contains only parents.
143
	pub fn last(&self) -> Option<&Junction> {
144
		self.interior.last()
145
	}
146

            
147
	/// Splits off the first interior junction, returning the remaining suffix (first item in tuple)
148
	/// and the first element (second item in tuple) or `None` if it was empty.
149
	pub fn split_first_interior(self) -> (MultiLocation, Option<Junction>) {
150
		let MultiLocation { parents, interior: junctions } = self;
151
		let (suffix, first) = junctions.split_first();
152
		let multilocation = MultiLocation { parents, interior: suffix };
153
		(multilocation, first)
154
	}
155

            
156
	/// Splits off the last interior junction, returning the remaining prefix (first item in tuple)
157
	/// and the last element (second item in tuple) or `None` if it was empty or if `self` only
158
	/// contains parents.
159
	pub fn split_last_interior(self) -> (MultiLocation, Option<Junction>) {
160
		let MultiLocation { parents, interior: junctions } = self;
161
		let (prefix, last) = junctions.split_last();
162
		let multilocation = MultiLocation { parents, interior: prefix };
163
		(multilocation, last)
164
	}
165

            
166
	/// Mutates `self`, suffixing its interior junctions with `new`. Returns `Err` with `new` in
167
	/// case of overflow.
168
	pub fn push_interior(&mut self, new: Junction) -> result::Result<(), Junction> {
169
		self.interior.push(new)
170
	}
171

            
172
	/// Mutates `self`, prefixing its interior junctions with `new`. Returns `Err` with `new` in
173
	/// case of overflow.
174
	pub fn push_front_interior(&mut self, new: Junction) -> result::Result<(), Junction> {
175
		self.interior.push_front(new)
176
	}
177

            
178
	/// Consumes `self` and returns a `MultiLocation` suffixed with `new`, or an `Err` with
179
	/// the original value of `self` in case of overflow.
180
	pub fn pushed_with_interior(self, new: Junction) -> result::Result<Self, (Self, Junction)> {
181
		match self.interior.pushed_with(new) {
182
			Ok(i) => Ok(MultiLocation { interior: i, parents: self.parents }),
183
			Err((i, j)) => Err((MultiLocation { interior: i, parents: self.parents }, j)),
184
		}
185
	}
186

            
187
	/// Consumes `self` and returns a `MultiLocation` prefixed with `new`, or an `Err` with the
188
	/// original value of `self` in case of overflow.
189
	pub fn pushed_front_with_interior(
190
		self,
191
		new: Junction,
192
	) -> result::Result<Self, (Self, Junction)> {
193
		match self.interior.pushed_front_with(new) {
194
			Ok(i) => Ok(MultiLocation { interior: i, parents: self.parents }),
195
			Err((i, j)) => Err((MultiLocation { interior: i, parents: self.parents }, j)),
196
		}
197
	}
198

            
199
	/// Returns the junction at index `i`, or `None` if the location is a parent or if the location
200
	/// does not contain that many elements.
201
	pub fn at(&self, i: usize) -> Option<&Junction> {
202
		let num_parents = self.parents as usize;
203
		if i < num_parents {
204
			return None
205
		}
206
		self.interior.at(i - num_parents)
207
	}
208

            
209
	/// Returns a mutable reference to the junction at index `i`, or `None` if the location is a
210
	/// parent or if it doesn't contain that many elements.
211
	pub fn at_mut(&mut self, i: usize) -> Option<&mut Junction> {
212
		let num_parents = self.parents as usize;
213
		if i < num_parents {
214
			return None
215
		}
216
		self.interior.at_mut(i - num_parents)
217
	}
218

            
219
	/// Decrements the parent count by 1.
220
	pub fn dec_parent(&mut self) {
221
		self.parents = self.parents.saturating_sub(1);
222
	}
223

            
224
	/// Removes the first interior junction from `self`, returning it
225
	/// (or `None` if it was empty or if `self` contains only parents).
226
	pub fn take_first_interior(&mut self) -> Option<Junction> {
227
		self.interior.take_first()
228
	}
229

            
230
	/// Removes the last element from `interior`, returning it (or `None` if it was empty or if
231
	/// `self` only contains parents).
232
	pub fn take_last(&mut self) -> Option<Junction> {
233
		self.interior.take_last()
234
	}
235

            
236
	/// Ensures that `self` has the same number of parents as `prefix`, its junctions begins with
237
	/// the junctions of `prefix` and that it has a single `Junction` item following.
238
	/// If so, returns a reference to this `Junction` item.
239
	///
240
	/// # Example
241
	/// ```rust
242
	/// # use staging_xcm::v2::{Junctions::*, Junction::*, MultiLocation};
243
	/// let mut m = MultiLocation::new(1, [PalletInstance(3), OnlyChild].into());
244
	/// assert_eq!(
245
	///     m.match_and_split(&MultiLocation::new(1, [PalletInstance(3)].into())),
246
	///     Some(&OnlyChild),
247
	/// );
248
	/// assert_eq!(m.match_and_split(&MultiLocation::new(1, Here)), None);
249
	/// ```
250
	pub fn match_and_split(&self, prefix: &MultiLocation) -> Option<&Junction> {
251
		if self.parents != prefix.parents {
252
			return None
253
		}
254
		self.interior.match_and_split(&prefix.interior)
255
	}
256

            
257
	/// Returns whether `self` has the same number of parents as `prefix` and its junctions begins
258
	/// with the junctions of `prefix`.
259
	///
260
	/// # Example
261
	/// ```rust
262
	/// # use staging_xcm::v2::{Junctions::*, Junction::*, MultiLocation};
263
	/// let m = MultiLocation::new(1, [PalletInstance(3), OnlyChild, OnlyChild].into());
264
	/// assert!(m.starts_with(&MultiLocation::new(1, [PalletInstance(3)].into())));
265
	/// assert!(!m.starts_with(&MultiLocation::new(1, [GeneralIndex(99)].into())));
266
	/// assert!(!m.starts_with(&MultiLocation::new(0, [PalletInstance(3)].into())));
267
	/// ```
268
	pub fn starts_with(&self, prefix: &MultiLocation) -> bool {
269
		if self.parents != prefix.parents {
270
			return false
271
		}
272
		self.interior.starts_with(&prefix.interior)
273
	}
274

            
275
	/// Mutate `self` so that it is suffixed with `suffix`.
276
	///
277
	/// Does not modify `self` and returns `Err` with `suffix` in case of overflow.
278
	///
279
	/// # Example
280
	/// ```rust
281
	/// # use staging_xcm::v2::{Junctions::*, Junction::*, MultiLocation};
282
	/// let mut m = MultiLocation::new(1, [Parachain(21)].into());
283
	/// assert_eq!(m.append_with([PalletInstance(3)].into()), Ok(()));
284
	/// assert_eq!(m, MultiLocation::new(1, [Parachain(21), PalletInstance(3)].into()));
285
	/// ```
286
	pub fn append_with(&mut self, suffix: Junctions) -> Result<(), Junctions> {
287
		if self.interior.len().saturating_add(suffix.len()) > MAX_JUNCTIONS {
288
			return Err(suffix)
289
		}
290
		for j in suffix.into_iter() {
291
			self.interior.push(j).expect("Already checked the sum of the len()s; qed")
292
		}
293
		Ok(())
294
	}
295

            
296
	/// Mutate `self` so that it is prefixed with `prefix`.
297
	///
298
	/// Does not modify `self` and returns `Err` with `prefix` in case of overflow.
299
	///
300
	/// # Example
301
	/// ```rust
302
	/// # use staging_xcm::v2::{Junctions::*, Junction::*, MultiLocation};
303
	/// let mut m = MultiLocation::new(2, [PalletInstance(3)].into());
304
	/// assert_eq!(m.prepend_with(MultiLocation::new(1, [Parachain(21), OnlyChild].into())), Ok(()));
305
	/// assert_eq!(m, MultiLocation::new(1, [PalletInstance(3)].into()));
306
	/// ```
307
	pub fn prepend_with(&mut self, mut prefix: MultiLocation) -> Result<(), MultiLocation> {
308
		//     prefix     self (suffix)
309
		// P .. P I .. I  p .. p i .. i
310
		let prepend_interior = prefix.interior.len().saturating_sub(self.parents as usize);
311
		let final_interior = self.interior.len().saturating_add(prepend_interior);
312
		if final_interior > MAX_JUNCTIONS {
313
			return Err(prefix)
314
		}
315
		let suffix_parents = (self.parents as usize).saturating_sub(prefix.interior.len());
316
		let final_parents = (prefix.parents as usize).saturating_add(suffix_parents);
317
		if final_parents > 255 {
318
			return Err(prefix)
319
		}
320

            
321
		// cancel out the final item on the prefix interior for one of the suffix's parents.
322
		while self.parents > 0 && prefix.take_last().is_some() {
323
			self.dec_parent();
324
		}
325

            
326
		// now we have either removed all suffix's parents or prefix interior.
327
		// this means we can combine the prefix's and suffix's remaining parents/interior since
328
		// we know that with at least one empty, the overall order will be respected:
329
		//     prefix     self (suffix)
330
		// P .. P   (I)   p .. p i .. i => P + p .. (no I) i
331
		//  -- or --
332
		// P .. P I .. I    (p)  i .. i => P (no p) .. I + i
333

            
334
		self.parents = self.parents.saturating_add(prefix.parents);
335
		for j in prefix.interior.into_iter().rev() {
336
			self.push_front_interior(j)
337
				.expect("final_interior no greater than MAX_JUNCTIONS; qed");
338
		}
339
		Ok(())
340
	}
341

            
342
	/// Consume `self` and return the value representing the same location from the point of view
343
	/// of `target`. The context of `self` is provided as `ancestry`.
344
	///
345
	/// Returns an `Err` with the unmodified `self` in the case of error.
346
	pub fn reanchored(
347
		mut self,
348
		target: &MultiLocation,
349
		ancestry: &MultiLocation,
350
	) -> Result<Self, Self> {
351
		match self.reanchor(target, ancestry) {
352
			Ok(()) => Ok(self),
353
			Err(()) => Err(self),
354
		}
355
	}
356

            
357
	/// Mutate `self` so that it represents the same location from the point of view of `target`.
358
	/// The context of `self` is provided as `ancestry`.
359
	///
360
	/// Does not modify `self` in case of overflow.
361
	pub fn reanchor(&mut self, target: &MultiLocation, ancestry: &MultiLocation) -> Result<(), ()> {
362
		// TODO: https://github.com/paritytech/polkadot/issues/4489 Optimize this.
363

            
364
		// 1. Use our `ancestry` to figure out how the `target` would address us.
365
		let inverted_target = ancestry.inverted(target)?;
366

            
367
		// 2. Prepend `inverted_target` to `self` to get self's location from the perspective of
368
		// `target`.
369
		self.prepend_with(inverted_target).map_err(|_| ())?;
370

            
371
		// 3. Given that we know some of `target` ancestry, ensure that any parents in `self` are
372
		// strictly needed.
373
		self.simplify(target.interior());
374

            
375
		Ok(())
376
	}
377

            
378
	/// Treating `self` as a context, determine how it would be referenced by a `target` location.
379
	pub fn inverted(&self, target: &MultiLocation) -> Result<MultiLocation, ()> {
380
		use Junction::OnlyChild;
381
		let mut ancestry = self.clone();
382
		let mut junctions = Junctions::Here;
383
		for _ in 0..target.parent_count() {
384
			junctions = junctions
385
				.pushed_front_with(ancestry.interior.take_last().unwrap_or(OnlyChild))
386
				.map_err(|_| ())?;
387
		}
388
		let parents = target.interior().len() as u8;
389
		Ok(MultiLocation::new(parents, junctions))
390
	}
391

            
392
	/// Remove any unneeded parents/junctions in `self` based on the given context it will be
393
	/// interpreted in.
394
	pub fn simplify(&mut self, context: &Junctions) {
395
		if context.len() < self.parents as usize {
396
			// Not enough context
397
			return
398
		}
399
		while self.parents > 0 {
400
			let maybe = context.at(context.len() - (self.parents as usize));
401
			match (self.interior.first(), maybe) {
402
				(Some(i), Some(j)) if i == j => {
403
					self.interior.take_first();
404
					self.parents -= 1;
405
				},
406
				_ => break,
407
			}
408
		}
409
	}
410
}
411

            
412
impl TryFrom<NewMultiLocation> for MultiLocation {
413
	type Error = ();
414
	fn try_from(x: NewMultiLocation) -> result::Result<Self, ()> {
415
		Ok(MultiLocation { parents: x.parents, interior: x.interior.try_into()? })
416
	}
417
}
418

            
419
/// A unit struct which can be converted into a `MultiLocation` of `parents` value 1.
420
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
421
pub struct Parent;
422
impl From<Parent> for MultiLocation {
423
	fn from(_: Parent) -> Self {
424
		MultiLocation { parents: 1, interior: Junctions::Here }
425
	}
426
}
427

            
428
/// A tuple struct which can be converted into a `MultiLocation` of `parents` value 1 with the inner
429
/// interior.
430
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
431
pub struct ParentThen(pub Junctions);
432
impl From<ParentThen> for MultiLocation {
433
	fn from(ParentThen(interior): ParentThen) -> Self {
434
		MultiLocation { parents: 1, interior }
435
	}
436
}
437

            
438
/// A unit struct which can be converted into a `MultiLocation` of the inner `parents` value.
439
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
440
pub struct Ancestor(pub u8);
441
impl From<Ancestor> for MultiLocation {
442
	fn from(Ancestor(parents): Ancestor) -> Self {
443
		MultiLocation { parents, interior: Junctions::Here }
444
	}
445
}
446

            
447
/// A unit struct which can be converted into a `MultiLocation` of the inner `parents` value and the
448
/// inner interior.
449
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
450
pub struct AncestorThen<Interior>(pub u8, pub Interior);
451
impl<Interior: Into<Junctions>> From<AncestorThen<Interior>> for MultiLocation {
452
	fn from(AncestorThen(parents, interior): AncestorThen<Interior>) -> Self {
453
		MultiLocation { parents, interior: interior.into() }
454
	}
455
}
456

            
457
xcm_procedural::impl_conversion_functions_for_multilocation_v2!();
458
xcm_procedural::impl_conversion_functions_for_junctions_v2!();
459

            
460
/// Maximum number of `Junction`s that a `Junctions` can contain.
461
const MAX_JUNCTIONS: usize = 8;
462

            
463
/// Non-parent junctions that can be constructed, up to the length of 8. This specific `Junctions`
464
/// implementation uses a Rust `enum` in order to make pattern matching easier.
465
///
466
/// Parent junctions cannot be constructed with this type. Refer to `MultiLocation` for
467
/// instructions on constructing parent junctions.
468
333
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
469
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
470
#[scale_info(replace_segment("staging_xcm", "xcm"))]
471
pub enum Junctions {
472
41376
	/// The interpreting consensus system.
473
41376
	Here,
474
4551
	/// A relative path comprising 1 junction.
475
4551
	X1(Junction),
476
1209
	/// A relative path comprising 2 junctions.
477
1209
	X2(Junction, Junction),
478
687
	/// A relative path comprising 3 junctions.
479
687
	X3(Junction, Junction, Junction),
480
1413
	/// A relative path comprising 4 junctions.
481
1413
	X4(Junction, Junction, Junction, Junction),
482
744
	/// A relative path comprising 5 junctions.
483
744
	X5(Junction, Junction, Junction, Junction, Junction),
484
384
	/// A relative path comprising 6 junctions.
485
384
	X6(Junction, Junction, Junction, Junction, Junction, Junction),
486
459
	/// A relative path comprising 7 junctions.
487
459
	X7(Junction, Junction, Junction, Junction, Junction, Junction, Junction),
488
1026
	/// A relative path comprising 8 junctions.
489
1026
	X8(Junction, Junction, Junction, Junction, Junction, Junction, Junction, Junction),
490
}
491

            
492
pub struct JunctionsIterator(Junctions);
493
impl Iterator for JunctionsIterator {
494
	type Item = Junction;
495
	fn next(&mut self) -> Option<Junction> {
496
		self.0.take_first()
497
	}
498
}
499

            
500
impl DoubleEndedIterator for JunctionsIterator {
501
	fn next_back(&mut self) -> Option<Junction> {
502
		self.0.take_last()
503
	}
504
}
505

            
506
pub struct JunctionsRefIterator<'a> {
507
	junctions: &'a Junctions,
508
	next: usize,
509
	back: usize,
510
}
511

            
512
impl<'a> Iterator for JunctionsRefIterator<'a> {
513
	type Item = &'a Junction;
514
	fn next(&mut self) -> Option<&'a Junction> {
515
		if self.next.saturating_add(self.back) >= self.junctions.len() {
516
			return None
517
		}
518

            
519
		let result = self.junctions.at(self.next);
520
		self.next += 1;
521
		result
522
	}
523
}
524

            
525
impl<'a> DoubleEndedIterator for JunctionsRefIterator<'a> {
526
	fn next_back(&mut self) -> Option<&'a Junction> {
527
		let next_back = self.back.saturating_add(1);
528
		// checked_sub here, because if the result is less than 0, we end iteration
529
		let index = self.junctions.len().checked_sub(next_back)?;
530
		if self.next > index {
531
			return None
532
		}
533
		self.back = next_back;
534

            
535
		self.junctions.at(index)
536
	}
537
}
538

            
539
impl<'a> IntoIterator for &'a Junctions {
540
	type Item = &'a Junction;
541
	type IntoIter = JunctionsRefIterator<'a>;
542
	fn into_iter(self) -> Self::IntoIter {
543
		JunctionsRefIterator { junctions: self, next: 0, back: 0 }
544
	}
545
}
546

            
547
impl IntoIterator for Junctions {
548
	type Item = Junction;
549
	type IntoIter = JunctionsIterator;
550
	fn into_iter(self) -> Self::IntoIter {
551
		JunctionsIterator(self)
552
	}
553
}
554

            
555
impl Junctions {
556
	/// Convert `self` into a `MultiLocation` containing 0 parents.
557
	///
558
	/// Similar to `Into::into`, except that this method can be used in a const evaluation context.
559
	pub const fn into(self) -> MultiLocation {
560
		MultiLocation { parents: 0, interior: self }
561
	}
562

            
563
	/// Convert `self` into a `MultiLocation` containing `n` parents.
564
	///
565
	/// Similar to `Self::into`, with the added ability to specify the number of parent junctions.
566
	pub const fn into_exterior(self, n: u8) -> MultiLocation {
567
		MultiLocation { parents: n, interior: self }
568
	}
569

            
570
	/// Returns first junction, or `None` if the location is empty.
571
	pub fn first(&self) -> Option<&Junction> {
572
		match &self {
573
			Junctions::Here => None,
574
			Junctions::X1(ref a) => Some(a),
575
			Junctions::X2(ref a, ..) => Some(a),
576
			Junctions::X3(ref a, ..) => Some(a),
577
			Junctions::X4(ref a, ..) => Some(a),
578
			Junctions::X5(ref a, ..) => Some(a),
579
			Junctions::X6(ref a, ..) => Some(a),
580
			Junctions::X7(ref a, ..) => Some(a),
581
			Junctions::X8(ref a, ..) => Some(a),
582
		}
583
	}
584

            
585
	/// Returns last junction, or `None` if the location is empty.
586
	pub fn last(&self) -> Option<&Junction> {
587
		match &self {
588
			Junctions::Here => None,
589
			Junctions::X1(ref a) => Some(a),
590
			Junctions::X2(.., ref a) => Some(a),
591
			Junctions::X3(.., ref a) => Some(a),
592
			Junctions::X4(.., ref a) => Some(a),
593
			Junctions::X5(.., ref a) => Some(a),
594
			Junctions::X6(.., ref a) => Some(a),
595
			Junctions::X7(.., ref a) => Some(a),
596
			Junctions::X8(.., ref a) => Some(a),
597
		}
598
	}
599

            
600
	/// Splits off the first junction, returning the remaining suffix (first item in tuple) and the
601
	/// first element (second item in tuple) or `None` if it was empty.
602
	pub fn split_first(self) -> (Junctions, Option<Junction>) {
603
		match self {
604
			Junctions::Here => (Junctions::Here, None),
605
			Junctions::X1(a) => (Junctions::Here, Some(a)),
606
			Junctions::X2(a, b) => (Junctions::X1(b), Some(a)),
607
			Junctions::X3(a, b, c) => (Junctions::X2(b, c), Some(a)),
608
			Junctions::X4(a, b, c, d) => (Junctions::X3(b, c, d), Some(a)),
609
			Junctions::X5(a, b, c, d, e) => (Junctions::X4(b, c, d, e), Some(a)),
610
			Junctions::X6(a, b, c, d, e, f) => (Junctions::X5(b, c, d, e, f), Some(a)),
611
			Junctions::X7(a, b, c, d, e, f, g) => (Junctions::X6(b, c, d, e, f, g), Some(a)),
612
			Junctions::X8(a, b, c, d, e, f, g, h) => (Junctions::X7(b, c, d, e, f, g, h), Some(a)),
613
		}
614
	}
615

            
616
	/// Splits off the last junction, returning the remaining prefix (first item in tuple) and the
617
	/// last element (second item in tuple) or `None` if it was empty.
618
	pub fn split_last(self) -> (Junctions, Option<Junction>) {
619
		match self {
620
			Junctions::Here => (Junctions::Here, None),
621
			Junctions::X1(a) => (Junctions::Here, Some(a)),
622
			Junctions::X2(a, b) => (Junctions::X1(a), Some(b)),
623
			Junctions::X3(a, b, c) => (Junctions::X2(a, b), Some(c)),
624
			Junctions::X4(a, b, c, d) => (Junctions::X3(a, b, c), Some(d)),
625
			Junctions::X5(a, b, c, d, e) => (Junctions::X4(a, b, c, d), Some(e)),
626
			Junctions::X6(a, b, c, d, e, f) => (Junctions::X5(a, b, c, d, e), Some(f)),
627
			Junctions::X7(a, b, c, d, e, f, g) => (Junctions::X6(a, b, c, d, e, f), Some(g)),
628
			Junctions::X8(a, b, c, d, e, f, g, h) => (Junctions::X7(a, b, c, d, e, f, g), Some(h)),
629
		}
630
	}
631

            
632
	/// Removes the first element from `self`, returning it (or `None` if it was empty).
633
	pub fn take_first(&mut self) -> Option<Junction> {
634
		let mut d = Junctions::Here;
635
		mem::swap(&mut *self, &mut d);
636
		let (tail, head) = d.split_first();
637
		*self = tail;
638
		head
639
	}
640

            
641
	/// Removes the last element from `self`, returning it (or `None` if it was empty).
642
	pub fn take_last(&mut self) -> Option<Junction> {
643
		let mut d = Junctions::Here;
644
		mem::swap(&mut *self, &mut d);
645
		let (head, tail) = d.split_last();
646
		*self = head;
647
		tail
648
	}
649

            
650
	/// Mutates `self` to be appended with `new` or returns an `Err` with `new` if would overflow.
651
	pub fn push(&mut self, new: Junction) -> result::Result<(), Junction> {
652
		let mut dummy = Junctions::Here;
653
		mem::swap(self, &mut dummy);
654
		match dummy.pushed_with(new) {
655
			Ok(s) => {
656
				*self = s;
657
				Ok(())
658
			},
659
			Err((s, j)) => {
660
				*self = s;
661
				Err(j)
662
			},
663
		}
664
	}
665

            
666
	/// Mutates `self` to be prepended with `new` or returns an `Err` with `new` if would overflow.
667
	pub fn push_front(&mut self, new: Junction) -> result::Result<(), Junction> {
668
		let mut dummy = Junctions::Here;
669
		mem::swap(self, &mut dummy);
670
		match dummy.pushed_front_with(new) {
671
			Ok(s) => {
672
				*self = s;
673
				Ok(())
674
			},
675
			Err((s, j)) => {
676
				*self = s;
677
				Err(j)
678
			},
679
		}
680
	}
681

            
682
	/// Consumes `self` and returns a `Junctions` suffixed with `new`, or an `Err` with the
683
	/// original value of `self` and `new` in case of overflow.
684
	pub fn pushed_with(self, new: Junction) -> result::Result<Self, (Self, Junction)> {
685
		Ok(match self {
686
			Junctions::Here => Junctions::X1(new),
687
			Junctions::X1(a) => Junctions::X2(a, new),
688
			Junctions::X2(a, b) => Junctions::X3(a, b, new),
689
			Junctions::X3(a, b, c) => Junctions::X4(a, b, c, new),
690
			Junctions::X4(a, b, c, d) => Junctions::X5(a, b, c, d, new),
691
			Junctions::X5(a, b, c, d, e) => Junctions::X6(a, b, c, d, e, new),
692
			Junctions::X6(a, b, c, d, e, f) => Junctions::X7(a, b, c, d, e, f, new),
693
			Junctions::X7(a, b, c, d, e, f, g) => Junctions::X8(a, b, c, d, e, f, g, new),
694
			s => Err((s, new))?,
695
		})
696
	}
697

            
698
	/// Consumes `self` and returns a `Junctions` prefixed with `new`, or an `Err` with the
699
	/// original value of `self` and `new` in case of overflow.
700
	pub fn pushed_front_with(self, new: Junction) -> result::Result<Self, (Self, Junction)> {
701
		Ok(match self {
702
			Junctions::Here => Junctions::X1(new),
703
			Junctions::X1(a) => Junctions::X2(new, a),
704
			Junctions::X2(a, b) => Junctions::X3(new, a, b),
705
			Junctions::X3(a, b, c) => Junctions::X4(new, a, b, c),
706
			Junctions::X4(a, b, c, d) => Junctions::X5(new, a, b, c, d),
707
			Junctions::X5(a, b, c, d, e) => Junctions::X6(new, a, b, c, d, e),
708
			Junctions::X6(a, b, c, d, e, f) => Junctions::X7(new, a, b, c, d, e, f),
709
			Junctions::X7(a, b, c, d, e, f, g) => Junctions::X8(new, a, b, c, d, e, f, g),
710
			s => Err((s, new))?,
711
		})
712
	}
713

            
714
	/// Returns the number of junctions in `self`.
715
	pub const fn len(&self) -> usize {
716
		match &self {
717
			Junctions::Here => 0,
718
			Junctions::X1(..) => 1,
719
			Junctions::X2(..) => 2,
720
			Junctions::X3(..) => 3,
721
			Junctions::X4(..) => 4,
722
			Junctions::X5(..) => 5,
723
			Junctions::X6(..) => 6,
724
			Junctions::X7(..) => 7,
725
			Junctions::X8(..) => 8,
726
		}
727
	}
728

            
729
	/// Returns the junction at index `i`, or `None` if the location doesn't contain that many
730
	/// elements.
731
	pub fn at(&self, i: usize) -> Option<&Junction> {
732
		Some(match (i, self) {
733
			(0, Junctions::X1(ref a)) => a,
734
			(0, Junctions::X2(ref a, ..)) => a,
735
			(0, Junctions::X3(ref a, ..)) => a,
736
			(0, Junctions::X4(ref a, ..)) => a,
737
			(0, Junctions::X5(ref a, ..)) => a,
738
			(0, Junctions::X6(ref a, ..)) => a,
739
			(0, Junctions::X7(ref a, ..)) => a,
740
			(0, Junctions::X8(ref a, ..)) => a,
741
			(1, Junctions::X2(_, ref a)) => a,
742
			(1, Junctions::X3(_, ref a, ..)) => a,
743
			(1, Junctions::X4(_, ref a, ..)) => a,
744
			(1, Junctions::X5(_, ref a, ..)) => a,
745
			(1, Junctions::X6(_, ref a, ..)) => a,
746
			(1, Junctions::X7(_, ref a, ..)) => a,
747
			(1, Junctions::X8(_, ref a, ..)) => a,
748
			(2, Junctions::X3(_, _, ref a)) => a,
749
			(2, Junctions::X4(_, _, ref a, ..)) => a,
750
			(2, Junctions::X5(_, _, ref a, ..)) => a,
751
			(2, Junctions::X6(_, _, ref a, ..)) => a,
752
			(2, Junctions::X7(_, _, ref a, ..)) => a,
753
			(2, Junctions::X8(_, _, ref a, ..)) => a,
754
			(3, Junctions::X4(_, _, _, ref a)) => a,
755
			(3, Junctions::X5(_, _, _, ref a, ..)) => a,
756
			(3, Junctions::X6(_, _, _, ref a, ..)) => a,
757
			(3, Junctions::X7(_, _, _, ref a, ..)) => a,
758
			(3, Junctions::X8(_, _, _, ref a, ..)) => a,
759
			(4, Junctions::X5(_, _, _, _, ref a)) => a,
760
			(4, Junctions::X6(_, _, _, _, ref a, ..)) => a,
761
			(4, Junctions::X7(_, _, _, _, ref a, ..)) => a,
762
			(4, Junctions::X8(_, _, _, _, ref a, ..)) => a,
763
			(5, Junctions::X6(_, _, _, _, _, ref a)) => a,
764
			(5, Junctions::X7(_, _, _, _, _, ref a, ..)) => a,
765
			(5, Junctions::X8(_, _, _, _, _, ref a, ..)) => a,
766
			(6, Junctions::X7(_, _, _, _, _, _, ref a)) => a,
767
			(6, Junctions::X8(_, _, _, _, _, _, ref a, ..)) => a,
768
			(7, Junctions::X8(_, _, _, _, _, _, _, ref a)) => a,
769
			_ => return None,
770
		})
771
	}
772

            
773
	/// Returns a mutable reference to the junction at index `i`, or `None` if the location doesn't
774
	/// contain that many elements.
775
	pub fn at_mut(&mut self, i: usize) -> Option<&mut Junction> {
776
		Some(match (i, self) {
777
			(0, Junctions::X1(ref mut a)) => a,
778
			(0, Junctions::X2(ref mut a, ..)) => a,
779
			(0, Junctions::X3(ref mut a, ..)) => a,
780
			(0, Junctions::X4(ref mut a, ..)) => a,
781
			(0, Junctions::X5(ref mut a, ..)) => a,
782
			(0, Junctions::X6(ref mut a, ..)) => a,
783
			(0, Junctions::X7(ref mut a, ..)) => a,
784
			(0, Junctions::X8(ref mut a, ..)) => a,
785
			(1, Junctions::X2(_, ref mut a)) => a,
786
			(1, Junctions::X3(_, ref mut a, ..)) => a,
787
			(1, Junctions::X4(_, ref mut a, ..)) => a,
788
			(1, Junctions::X5(_, ref mut a, ..)) => a,
789
			(1, Junctions::X6(_, ref mut a, ..)) => a,
790
			(1, Junctions::X7(_, ref mut a, ..)) => a,
791
			(1, Junctions::X8(_, ref mut a, ..)) => a,
792
			(2, Junctions::X3(_, _, ref mut a)) => a,
793
			(2, Junctions::X4(_, _, ref mut a, ..)) => a,
794
			(2, Junctions::X5(_, _, ref mut a, ..)) => a,
795
			(2, Junctions::X6(_, _, ref mut a, ..)) => a,
796
			(2, Junctions::X7(_, _, ref mut a, ..)) => a,
797
			(2, Junctions::X8(_, _, ref mut a, ..)) => a,
798
			(3, Junctions::X4(_, _, _, ref mut a)) => a,
799
			(3, Junctions::X5(_, _, _, ref mut a, ..)) => a,
800
			(3, Junctions::X6(_, _, _, ref mut a, ..)) => a,
801
			(3, Junctions::X7(_, _, _, ref mut a, ..)) => a,
802
			(3, Junctions::X8(_, _, _, ref mut a, ..)) => a,
803
			(4, Junctions::X5(_, _, _, _, ref mut a)) => a,
804
			(4, Junctions::X6(_, _, _, _, ref mut a, ..)) => a,
805
			(4, Junctions::X7(_, _, _, _, ref mut a, ..)) => a,
806
			(4, Junctions::X8(_, _, _, _, ref mut a, ..)) => a,
807
			(5, Junctions::X6(_, _, _, _, _, ref mut a)) => a,
808
			(5, Junctions::X7(_, _, _, _, _, ref mut a, ..)) => a,
809
			(5, Junctions::X8(_, _, _, _, _, ref mut a, ..)) => a,
810
			(6, Junctions::X7(_, _, _, _, _, _, ref mut a)) => a,
811
			(6, Junctions::X8(_, _, _, _, _, _, ref mut a, ..)) => a,
812
			(7, Junctions::X8(_, _, _, _, _, _, _, ref mut a)) => a,
813
			_ => return None,
814
		})
815
	}
816

            
817
	/// Returns a reference iterator over the junctions.
818
	pub fn iter(&self) -> JunctionsRefIterator {
819
		JunctionsRefIterator { junctions: self, next: 0, back: 0 }
820
	}
821

            
822
	/// Returns a reference iterator over the junctions in reverse.
823
	#[deprecated(note = "Please use iter().rev()")]
824
	pub fn iter_rev(&self) -> impl Iterator + '_ {
825
		self.iter().rev()
826
	}
827

            
828
	/// Consumes `self` and returns an iterator over the junctions in reverse.
829
	#[deprecated(note = "Please use into_iter().rev()")]
830
	pub fn into_iter_rev(self) -> impl Iterator {
831
		self.into_iter().rev()
832
	}
833

            
834
	/// Ensures that self begins with `prefix` and that it has a single `Junction` item following.
835
	/// If so, returns a reference to this `Junction` item.
836
	///
837
	/// # Example
838
	/// ```rust
839
	/// # use staging_xcm::v2::{Junctions::*, Junction::*};
840
	/// let mut m = X3(Parachain(2), PalletInstance(3), OnlyChild);
841
	/// assert_eq!(m.match_and_split(&X2(Parachain(2), PalletInstance(3))), Some(&OnlyChild));
842
	/// assert_eq!(m.match_and_split(&X1(Parachain(2))), None);
843
	/// ```
844
	pub fn match_and_split(&self, prefix: &Junctions) -> Option<&Junction> {
845
		if prefix.len() + 1 != self.len() || !self.starts_with(prefix) {
846
			return None
847
		}
848
		self.at(prefix.len())
849
	}
850

            
851
	/// Returns whether `self` begins with or is equal to `prefix`.
852
	///
853
	/// # Example
854
	/// ```rust
855
	/// # use staging_xcm::v2::{Junctions::*, Junction::*};
856
	/// let mut j = X3(Parachain(2), PalletInstance(3), OnlyChild);
857
	/// assert!(j.starts_with(&X2(Parachain(2), PalletInstance(3))));
858
	/// assert!(j.starts_with(&j));
859
	/// assert!(j.starts_with(&X1(Parachain(2))));
860
	/// assert!(!j.starts_with(&X1(Parachain(999))));
861
	/// assert!(!j.starts_with(&X4(Parachain(2), PalletInstance(3), OnlyChild, OnlyChild)));
862
	/// ```
863
	pub fn starts_with(&self, prefix: &Junctions) -> bool {
864
		if self.len() < prefix.len() {
865
			return false
866
		}
867
		prefix.iter().zip(self.iter()).all(|(l, r)| l == r)
868
	}
869
}
870

            
871
impl TryFrom<MultiLocation> for Junctions {
872
	type Error = ();
873
	fn try_from(x: MultiLocation) -> result::Result<Self, ()> {
874
		if x.parents > 0 {
875
			Err(())
876
		} else {
877
			Ok(x.interior)
878
		}
879
	}
880
}
881

            
882
#[cfg(test)]
883
mod tests {
884
	use super::{Ancestor, AncestorThen, Junctions::*, MultiLocation, Parent, ParentThen};
885
	use crate::opaque::v2::{Junction::*, NetworkId::*};
886
	use codec::{Decode, Encode};
887

            
888
	#[test]
889
	fn inverted_works() {
890
		let ancestry: MultiLocation = (Parachain(1000), PalletInstance(42)).into();
891
		let target = (Parent, PalletInstance(69)).into();
892
		let expected = (Parent, PalletInstance(42)).into();
893
		let inverted = ancestry.inverted(&target).unwrap();
894
		assert_eq!(inverted, expected);
895

            
896
		let ancestry: MultiLocation = (Parachain(1000), PalletInstance(42), GeneralIndex(1)).into();
897
		let target = (Parent, Parent, PalletInstance(69), GeneralIndex(2)).into();
898
		let expected = (Parent, Parent, PalletInstance(42), GeneralIndex(1)).into();
899
		let inverted = ancestry.inverted(&target).unwrap();
900
		assert_eq!(inverted, expected);
901
	}
902

            
903
	#[test]
904
	fn simplify_basic_works() {
905
		let mut location: MultiLocation =
906
			(Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into();
907
		let context = X2(Parachain(1000), PalletInstance(42));
908
		let expected = GeneralIndex(69).into();
909
		location.simplify(&context);
910
		assert_eq!(location, expected);
911

            
912
		let mut location: MultiLocation = (Parent, PalletInstance(42), GeneralIndex(69)).into();
913
		let context = X1(PalletInstance(42));
914
		let expected = GeneralIndex(69).into();
915
		location.simplify(&context);
916
		assert_eq!(location, expected);
917

            
918
		let mut location: MultiLocation = (Parent, PalletInstance(42), GeneralIndex(69)).into();
919
		let context = X2(Parachain(1000), PalletInstance(42));
920
		let expected = GeneralIndex(69).into();
921
		location.simplify(&context);
922
		assert_eq!(location, expected);
923

            
924
		let mut location: MultiLocation =
925
			(Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into();
926
		let context = X3(OnlyChild, Parachain(1000), PalletInstance(42));
927
		let expected = GeneralIndex(69).into();
928
		location.simplify(&context);
929
		assert_eq!(location, expected);
930
	}
931

            
932
	#[test]
933
	fn simplify_incompatible_location_fails() {
934
		let mut location: MultiLocation =
935
			(Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into();
936
		let context = X3(Parachain(1000), PalletInstance(42), GeneralIndex(42));
937
		let expected =
938
			(Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into();
939
		location.simplify(&context);
940
		assert_eq!(location, expected);
941

            
942
		let mut location: MultiLocation =
943
			(Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into();
944
		let context = X1(Parachain(1000));
945
		let expected =
946
			(Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into();
947
		location.simplify(&context);
948
		assert_eq!(location, expected);
949
	}
950

            
951
	#[test]
952
	fn reanchor_works() {
953
		let mut id: MultiLocation = (Parent, Parachain(1000), GeneralIndex(42)).into();
954
		let ancestry = Parachain(2000).into();
955
		let target = (Parent, Parachain(1000)).into();
956
		let expected = GeneralIndex(42).into();
957
		id.reanchor(&target, &ancestry).unwrap();
958
		assert_eq!(id, expected);
959
	}
960

            
961
	#[test]
962
	fn encode_and_decode_works() {
963
		let m = MultiLocation {
964
			parents: 1,
965
			interior: X2(Parachain(42), AccountIndex64 { network: Any, index: 23 }),
966
		};
967
		let encoded = m.encode();
968
		assert_eq!(encoded, [1, 2, 0, 168, 2, 0, 92].to_vec());
969
		let decoded = MultiLocation::decode(&mut &encoded[..]);
970
		assert_eq!(decoded, Ok(m));
971
	}
972

            
973
	#[test]
974
	fn match_and_split_works() {
975
		let m = MultiLocation {
976
			parents: 1,
977
			interior: X2(Parachain(42), AccountIndex64 { network: Any, index: 23 }),
978
		};
979
		assert_eq!(m.match_and_split(&MultiLocation { parents: 1, interior: Here }), None);
980
		assert_eq!(
981
			m.match_and_split(&MultiLocation { parents: 1, interior: X1(Parachain(42)) }),
982
			Some(&AccountIndex64 { network: Any, index: 23 })
983
		);
984
		assert_eq!(m.match_and_split(&m), None);
985
	}
986

            
987
	#[test]
988
	fn starts_with_works() {
989
		let full: MultiLocation =
990
			(Parent, Parachain(1000), AccountId32 { network: Any, id: [0; 32] }).into();
991
		let identity: MultiLocation = full.clone();
992
		let prefix: MultiLocation = (Parent, Parachain(1000)).into();
993
		let wrong_parachain: MultiLocation = (Parent, Parachain(1001)).into();
994
		let wrong_account: MultiLocation =
995
			(Parent, Parachain(1000), AccountId32 { network: Any, id: [1; 32] }).into();
996
		let no_parents: MultiLocation = (Parachain(1000)).into();
997
		let too_many_parents: MultiLocation = (Parent, Parent, Parachain(1000)).into();
998

            
999
		assert!(full.starts_with(&identity));
		assert!(full.starts_with(&prefix));
		assert!(!full.starts_with(&wrong_parachain));
		assert!(!full.starts_with(&wrong_account));
		assert!(!full.starts_with(&no_parents));
		assert!(!full.starts_with(&too_many_parents));
	}
	#[test]
	fn append_with_works() {
		let acc = AccountIndex64 { network: Any, index: 23 };
		let mut m = MultiLocation { parents: 1, interior: X1(Parachain(42)) };
		assert_eq!(m.append_with(X2(PalletInstance(3), acc.clone())), Ok(()));
		assert_eq!(
			m,
			MultiLocation {
				parents: 1,
				interior: X3(Parachain(42), PalletInstance(3), acc.clone())
			}
		);
		// cannot append to create overly long multilocation
		let acc = AccountIndex64 { network: Any, index: 23 };
		let m = MultiLocation {
			parents: 254,
			interior: X5(Parachain(42), OnlyChild, OnlyChild, OnlyChild, OnlyChild),
		};
		let suffix = X4(PalletInstance(3), acc.clone(), OnlyChild, OnlyChild);
		assert_eq!(m.clone().append_with(suffix.clone()), Err(suffix));
	}
	#[test]
	fn prepend_with_works() {
		let mut m = MultiLocation {
			parents: 1,
			interior: X2(Parachain(42), AccountIndex64 { network: Any, index: 23 }),
		};
		assert_eq!(m.prepend_with(MultiLocation { parents: 1, interior: X1(OnlyChild) }), Ok(()));
		assert_eq!(
			m,
			MultiLocation {
				parents: 1,
				interior: X2(Parachain(42), AccountIndex64 { network: Any, index: 23 })
			}
		);
		// cannot prepend to create overly long multilocation
		let mut m = MultiLocation { parents: 254, interior: X1(Parachain(42)) };
		let prefix = MultiLocation { parents: 2, interior: Here };
		assert_eq!(m.prepend_with(prefix.clone()), Err(prefix));
		let prefix = MultiLocation { parents: 1, interior: Here };
		assert_eq!(m.prepend_with(prefix), Ok(()));
		assert_eq!(m, MultiLocation { parents: 255, interior: X1(Parachain(42)) });
	}
	#[test]
	fn double_ended_ref_iteration_works() {
		let m = X3(Parachain(1000), Parachain(3), PalletInstance(5));
		let mut iter = m.iter();
		let first = iter.next().unwrap();
		assert_eq!(first, &Parachain(1000));
		let third = iter.next_back().unwrap();
		assert_eq!(third, &PalletInstance(5));
		let second = iter.next_back().unwrap();
		assert_eq!(iter.next(), None);
		assert_eq!(iter.next_back(), None);
		assert_eq!(second, &Parachain(3));
		let res = Here
			.pushed_with(first.clone())
			.unwrap()
			.pushed_with(second.clone())
			.unwrap()
			.pushed_with(third.clone())
			.unwrap();
		assert_eq!(m, res);
		// make sure there's no funny business with the 0 indexing
		let m = Here;
		let mut iter = m.iter();
		assert_eq!(iter.next(), None);
		assert_eq!(iter.next_back(), None);
	}
	#[test]
	fn conversion_from_other_types_works() {
		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)]);
	}
}