1use super::Junction;
20use crate::v3::MultiLocation as NewMultiLocation;
21use codec::{Decode, Encode, MaxEncodedLen};
22use core::{mem, result};
23use scale_info::TypeInfo;
24
25#[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"))]
54pub struct MultiLocation {
55 pub parents: u8,
57 pub interior: Junctions,
59}
60
61impl Default for MultiLocation {
62 fn default() -> Self {
63 Self { parents: 0, interior: Junctions::Here }
64 }
65}
66
67pub type InteriorMultiLocation = Junctions;
71
72impl MultiLocation {
73 pub fn new(parents: u8, junctions: Junctions) -> MultiLocation {
75 MultiLocation { parents, interior: junctions }
76 }
77
78 pub fn versioned(self) -> crate::VersionedLocation {
80 self.into()
81 }
82
83 pub const fn here() -> MultiLocation {
87 MultiLocation { parents: 0, interior: Junctions::Here }
88 }
89
90 pub const fn parent() -> MultiLocation {
92 MultiLocation { parents: 1, interior: Junctions::Here }
93 }
94
95 pub const fn grandparent() -> MultiLocation {
97 MultiLocation { parents: 2, interior: Junctions::Here }
98 }
99
100 pub const fn ancestor(parents: u8) -> MultiLocation {
102 MultiLocation { parents, interior: Junctions::Here }
103 }
104
105 pub const fn is_here(&self) -> bool {
107 self.parents == 0 && self.interior.len() == 0
108 }
109
110 pub fn interior(&self) -> &Junctions {
112 &self.interior
113 }
114
115 pub fn interior_mut(&mut self) -> &mut Junctions {
117 &mut self.interior
118 }
119
120 pub const fn parent_count(&self) -> u8 {
122 self.parents
123 }
124
125 pub const fn contains_parents_only(&self, count: u8) -> bool {
128 matches!(self.interior, Junctions::Here) && self.parents == count
129 }
130
131 pub const fn len(&self) -> usize {
133 self.parent_count() as usize + self.interior.len()
134 }
135
136 pub fn first_interior(&self) -> Option<&Junction> {
139 self.interior.first()
140 }
141
142 pub fn last(&self) -> Option<&Junction> {
144 self.interior.last()
145 }
146
147 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 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 pub fn push_interior(&mut self, new: Junction) -> result::Result<(), Junction> {
169 self.interior.push(new)
170 }
171
172 pub fn push_front_interior(&mut self, new: Junction) -> result::Result<(), Junction> {
175 self.interior.push_front(new)
176 }
177
178 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 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 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 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 pub fn dec_parent(&mut self) {
221 self.parents = self.parents.saturating_sub(1);
222 }
223
224 pub fn take_first_interior(&mut self) -> Option<Junction> {
227 self.interior.take_first()
228 }
229
230 pub fn take_last(&mut self) -> Option<Junction> {
233 self.interior.take_last()
234 }
235
236 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 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 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 pub fn prepend_with(&mut self, mut prefix: MultiLocation) -> Result<(), MultiLocation> {
308 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 while self.parents > 0 && prefix.take_last().is_some() {
323 self.dec_parent();
324 }
325
326 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 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 pub fn reanchor(&mut self, target: &MultiLocation, ancestry: &MultiLocation) -> Result<(), ()> {
362 let inverted_target = ancestry.inverted(target)?;
366
367 self.prepend_with(inverted_target).map_err(|_| ())?;
370
371 self.simplify(target.interior());
374
375 Ok(())
376 }
377
378 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 pub fn simplify(&mut self, context: &Junctions) {
395 if context.len() < self.parents as usize {
396 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
412impl 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#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
421pub struct Parent;
422impl From<Parent> for MultiLocation {
423 fn from(_: Parent) -> Self {
424 MultiLocation { parents: 1, interior: Junctions::Here }
425 }
426}
427
428#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
431pub struct ParentThen(pub Junctions);
432impl From<ParentThen> for MultiLocation {
433 fn from(ParentThen(interior): ParentThen) -> Self {
434 MultiLocation { parents: 1, interior }
435 }
436}
437
438#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
440pub struct Ancestor(pub u8);
441impl From<Ancestor> for MultiLocation {
442 fn from(Ancestor(parents): Ancestor) -> Self {
443 MultiLocation { parents, interior: Junctions::Here }
444 }
445}
446
447#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
450pub struct AncestorThen<Interior>(pub u8, pub Interior);
451impl<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
457xcm_procedural::impl_conversion_functions_for_multilocation_v2!();
458xcm_procedural::impl_conversion_functions_for_junctions_v2!();
459
460const MAX_JUNCTIONS: usize = 8;
462
463#[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"))]
471pub enum Junctions {
472 Here,
474 X1(Junction),
476 X2(Junction, Junction),
478 X3(Junction, Junction, Junction),
480 X4(Junction, Junction, Junction, Junction),
482 X5(Junction, Junction, Junction, Junction, Junction),
484 X6(Junction, Junction, Junction, Junction, Junction, Junction),
486 X7(Junction, Junction, Junction, Junction, Junction, Junction, Junction),
488 X8(Junction, Junction, Junction, Junction, Junction, Junction, Junction, Junction),
490}
491
492pub struct JunctionsIterator(Junctions);
493impl Iterator for JunctionsIterator {
494 type Item = Junction;
495 fn next(&mut self) -> Option<Junction> {
496 self.0.take_first()
497 }
498}
499
500impl DoubleEndedIterator for JunctionsIterator {
501 fn next_back(&mut self) -> Option<Junction> {
502 self.0.take_last()
503 }
504}
505
506pub struct JunctionsRefIterator<'a> {
507 junctions: &'a Junctions,
508 next: usize,
509 back: usize,
510}
511
512impl<'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
525impl<'a> DoubleEndedIterator for JunctionsRefIterator<'a> {
526 fn next_back(&mut self) -> Option<&'a Junction> {
527 let next_back = self.back.saturating_add(1);
528 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
539impl<'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
547impl IntoIterator for Junctions {
548 type Item = Junction;
549 type IntoIter = JunctionsIterator;
550 fn into_iter(self) -> Self::IntoIter {
551 JunctionsIterator(self)
552 }
553}
554
555impl Junctions {
556 pub const fn into(self) -> MultiLocation {
560 MultiLocation { parents: 0, interior: self }
561 }
562
563 pub const fn into_exterior(self, n: u8) -> MultiLocation {
567 MultiLocation { parents: n, interior: self }
568 }
569
570 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 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 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 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 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 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 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 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 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 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 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 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 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 pub fn iter(&self) -> JunctionsRefIterator {
819 JunctionsRefIterator { junctions: self, next: 0, back: 0 }
820 }
821
822 #[deprecated(note = "Please use iter().rev()")]
824 pub fn iter_rev(&self) -> impl Iterator + '_ {
825 self.iter().rev()
826 }
827
828 #[deprecated(note = "Please use into_iter().rev()")]
830 pub fn into_iter_rev(self) -> impl Iterator {
831 self.into_iter().rev()
832 }
833
834 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 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
871impl 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)]
883mod 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));
1000 assert!(full.starts_with(&prefix));
1001 assert!(!full.starts_with(&wrong_parachain));
1002 assert!(!full.starts_with(&wrong_account));
1003 assert!(!full.starts_with(&no_parents));
1004 assert!(!full.starts_with(&too_many_parents));
1005 }
1006
1007 #[test]
1008 fn append_with_works() {
1009 let acc = AccountIndex64 { network: Any, index: 23 };
1010 let mut m = MultiLocation { parents: 1, interior: X1(Parachain(42)) };
1011 assert_eq!(m.append_with(X2(PalletInstance(3), acc.clone())), Ok(()));
1012 assert_eq!(
1013 m,
1014 MultiLocation {
1015 parents: 1,
1016 interior: X3(Parachain(42), PalletInstance(3), acc.clone())
1017 }
1018 );
1019
1020 let acc = AccountIndex64 { network: Any, index: 23 };
1022 let m = MultiLocation {
1023 parents: 254,
1024 interior: X5(Parachain(42), OnlyChild, OnlyChild, OnlyChild, OnlyChild),
1025 };
1026 let suffix = X4(PalletInstance(3), acc.clone(), OnlyChild, OnlyChild);
1027 assert_eq!(m.clone().append_with(suffix.clone()), Err(suffix));
1028 }
1029
1030 #[test]
1031 fn prepend_with_works() {
1032 let mut m = MultiLocation {
1033 parents: 1,
1034 interior: X2(Parachain(42), AccountIndex64 { network: Any, index: 23 }),
1035 };
1036 assert_eq!(m.prepend_with(MultiLocation { parents: 1, interior: X1(OnlyChild) }), Ok(()));
1037 assert_eq!(
1038 m,
1039 MultiLocation {
1040 parents: 1,
1041 interior: X2(Parachain(42), AccountIndex64 { network: Any, index: 23 })
1042 }
1043 );
1044
1045 let mut m = MultiLocation { parents: 254, interior: X1(Parachain(42)) };
1047 let prefix = MultiLocation { parents: 2, interior: Here };
1048 assert_eq!(m.prepend_with(prefix.clone()), Err(prefix));
1049
1050 let prefix = MultiLocation { parents: 1, interior: Here };
1051 assert_eq!(m.prepend_with(prefix), Ok(()));
1052 assert_eq!(m, MultiLocation { parents: 255, interior: X1(Parachain(42)) });
1053 }
1054
1055 #[test]
1056 fn double_ended_ref_iteration_works() {
1057 let m = X3(Parachain(1000), Parachain(3), PalletInstance(5));
1058 let mut iter = m.iter();
1059
1060 let first = iter.next().unwrap();
1061 assert_eq!(first, &Parachain(1000));
1062 let third = iter.next_back().unwrap();
1063 assert_eq!(third, &PalletInstance(5));
1064 let second = iter.next_back().unwrap();
1065 assert_eq!(iter.next(), None);
1066 assert_eq!(iter.next_back(), None);
1067 assert_eq!(second, &Parachain(3));
1068
1069 let res = Here
1070 .pushed_with(first.clone())
1071 .unwrap()
1072 .pushed_with(second.clone())
1073 .unwrap()
1074 .pushed_with(third.clone())
1075 .unwrap();
1076 assert_eq!(m, res);
1077
1078 let m = Here;
1080 let mut iter = m.iter();
1081
1082 assert_eq!(iter.next(), None);
1083 assert_eq!(iter.next_back(), None);
1084 }
1085
1086 #[test]
1087 fn conversion_from_other_types_works() {
1088 fn takes_multilocation<Arg: Into<MultiLocation>>(_arg: Arg) {}
1089
1090 takes_multilocation(Parent);
1091 takes_multilocation(Here);
1092 takes_multilocation(X1(Parachain(42)));
1093 takes_multilocation((255, PalletInstance(8)));
1094 takes_multilocation((Ancestor(5), Parachain(1), PalletInstance(3)));
1095 takes_multilocation((Ancestor(2), Here));
1096 takes_multilocation(AncestorThen(
1097 3,
1098 X2(Parachain(43), AccountIndex64 { network: Any, index: 155 }),
1099 ));
1100 takes_multilocation((Parent, AccountId32 { network: Any, id: [0; 32] }));
1101 takes_multilocation((Parent, Here));
1102 takes_multilocation(ParentThen(X1(Parachain(75))));
1103 takes_multilocation([Parachain(100), PalletInstance(3)]);
1104 }
1105}