1use super::{traits::Reanchorable, Junction, Junctions};
20use crate::{v3::MultiLocation as OldLocation, v5::Location as NewLocation, VersionedLocation};
21use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
22use core::result;
23use scale_info::TypeInfo;
24
25#[derive(
52 Clone,
53 Decode,
54 DecodeWithMemTracking,
55 Encode,
56 Eq,
57 PartialEq,
58 Ord,
59 PartialOrd,
60 Debug,
61 TypeInfo,
62 MaxEncodedLen,
63 serde::Serialize,
64 serde::Deserialize,
65)]
66pub struct Location {
67 pub parents: u8,
69 pub interior: Junctions,
71}
72
73impl Default for Location {
74 fn default() -> Self {
75 Self { parents: 0, interior: Junctions::Here }
76 }
77}
78
79pub type InteriorLocation = Junctions;
83
84impl Location {
85 pub fn new(parents: u8, interior: impl Into<Junctions>) -> Location {
87 Location { parents, interior: interior.into() }
88 }
89
90 pub const fn into_versioned(self) -> VersionedLocation {
92 VersionedLocation::V4(self)
93 }
94
95 pub const fn here() -> Location {
99 Location { parents: 0, interior: Junctions::Here }
100 }
101
102 pub const fn parent() -> Location {
104 Location { parents: 1, interior: Junctions::Here }
105 }
106
107 pub const fn ancestor(parents: u8) -> Location {
109 Location { parents, interior: Junctions::Here }
110 }
111
112 pub fn is_here(&self) -> bool {
114 self.parents == 0 && self.interior.len() == 0
115 }
116
117 pub fn remove_network_id(&mut self) {
119 self.interior.remove_network_id();
120 }
121
122 pub fn interior(&self) -> &Junctions {
124 &self.interior
125 }
126
127 pub fn interior_mut(&mut self) -> &mut Junctions {
129 &mut self.interior
130 }
131
132 pub const fn parent_count(&self) -> u8 {
134 self.parents
135 }
136
137 pub fn unpack(&self) -> (u8, &[Junction]) {
151 (self.parents, self.interior.as_slice())
152 }
153
154 pub const fn contains_parents_only(&self, count: u8) -> bool {
157 matches!(self.interior, Junctions::Here) && self.parents == count
158 }
159
160 pub fn len(&self) -> usize {
162 self.parent_count() as usize + self.interior.len()
163 }
164
165 pub fn first_interior(&self) -> Option<&Junction> {
168 self.interior.first()
169 }
170
171 pub fn last(&self) -> Option<&Junction> {
173 self.interior.last()
174 }
175
176 pub fn split_first_interior(self) -> (Location, Option<Junction>) {
179 let Location { parents, interior: junctions } = self;
180 let (suffix, first) = junctions.split_first();
181 let location = Location { parents, interior: suffix };
182 (location, first)
183 }
184
185 pub fn split_last_interior(self) -> (Location, Option<Junction>) {
189 let Location { parents, interior: junctions } = self;
190 let (prefix, last) = junctions.split_last();
191 let location = Location { parents, interior: prefix };
192 (location, last)
193 }
194
195 pub fn push_interior(&mut self, new: impl Into<Junction>) -> result::Result<(), Junction> {
198 self.interior.push(new)
199 }
200
201 pub fn push_front_interior(
204 &mut self,
205 new: impl Into<Junction>,
206 ) -> result::Result<(), Junction> {
207 self.interior.push_front(new)
208 }
209
210 pub fn pushed_with_interior(
213 self,
214 new: impl Into<Junction>,
215 ) -> result::Result<Self, (Self, Junction)> {
216 match self.interior.pushed_with(new) {
217 Ok(i) => Ok(Location { interior: i, parents: self.parents }),
218 Err((i, j)) => Err((Location { interior: i, parents: self.parents }, j)),
219 }
220 }
221
222 pub fn pushed_front_with_interior(
225 self,
226 new: impl Into<Junction>,
227 ) -> result::Result<Self, (Self, Junction)> {
228 match self.interior.pushed_front_with(new) {
229 Ok(i) => Ok(Location { interior: i, parents: self.parents }),
230 Err((i, j)) => Err((Location { interior: i, parents: self.parents }, j)),
231 }
232 }
233
234 pub fn at(&self, i: usize) -> Option<&Junction> {
237 let num_parents = self.parents as usize;
238 if i < num_parents {
239 return None
240 }
241 self.interior.at(i - num_parents)
242 }
243
244 pub fn at_mut(&mut self, i: usize) -> Option<&mut Junction> {
247 let num_parents = self.parents as usize;
248 if i < num_parents {
249 return None
250 }
251 self.interior.at_mut(i - num_parents)
252 }
253
254 pub fn dec_parent(&mut self) {
256 self.parents = self.parents.saturating_sub(1);
257 }
258
259 pub fn take_first_interior(&mut self) -> Option<Junction> {
262 self.interior.take_first()
263 }
264
265 pub fn take_last(&mut self) -> Option<Junction> {
268 self.interior.take_last()
269 }
270
271 pub fn match_and_split(&self, prefix: &Location) -> Option<&Junction> {
288 if self.parents != prefix.parents {
289 return None
290 }
291 self.interior.match_and_split(&prefix.interior)
292 }
293
294 pub fn starts_with(&self, prefix: &Location) -> bool {
295 self.parents == prefix.parents && self.interior.starts_with(&prefix.interior)
296 }
297
298 pub fn append_with(&mut self, suffix: impl Into<Self>) -> Result<(), Self> {
312 let prefix = core::mem::replace(self, suffix.into());
313 match self.prepend_with(prefix) {
314 Ok(()) => Ok(()),
315 Err(prefix) => Err(core::mem::replace(self, prefix)),
316 }
317 }
318
319 pub fn appended_with(mut self, suffix: impl Into<Self>) -> Result<Self, (Self, Self)> {
333 match self.append_with(suffix) {
334 Ok(()) => Ok(self),
335 Err(suffix) => Err((self, suffix)),
336 }
337 }
338
339 pub fn prepend_with(&mut self, prefix: impl Into<Self>) -> Result<(), Self> {
353 let mut prefix = prefix.into();
356 let prepend_interior = prefix.interior.len().saturating_sub(self.parents as usize);
357 let final_interior = self.interior.len().saturating_add(prepend_interior);
358 if final_interior > super::junctions::MAX_JUNCTIONS {
359 return Err(prefix)
360 }
361 let suffix_parents = (self.parents as usize).saturating_sub(prefix.interior.len());
362 let final_parents = (prefix.parents as usize).saturating_add(suffix_parents);
363 if final_parents > 255 {
364 return Err(prefix)
365 }
366
367 while self.parents > 0 && prefix.take_last().is_some() {
369 self.dec_parent();
370 }
371
372 self.parents = self.parents.saturating_add(prefix.parents);
381 for j in prefix.interior.into_iter().rev() {
382 self.push_front_interior(j)
383 .expect("final_interior no greater than MAX_JUNCTIONS; qed");
384 }
385 Ok(())
386 }
387
388 pub fn prepended_with(mut self, prefix: impl Into<Self>) -> Result<Self, (Self, Self)> {
402 match self.prepend_with(prefix) {
403 Ok(()) => Ok(self),
404 Err(prefix) => Err((self, prefix)),
405 }
406 }
407
408 pub fn simplify(&mut self, context: &Junctions) {
411 if context.len() < self.parents as usize {
412 return
414 }
415 while self.parents > 0 {
416 let maybe = context.at(context.len() - (self.parents as usize));
417 match (self.interior.first(), maybe) {
418 (Some(i), Some(j)) if i == j => {
419 self.interior.take_first();
420 self.parents -= 1;
421 },
422 _ => break,
423 }
424 }
425 }
426
427 pub fn chain_location(&self) -> Location {
429 let mut clone = self.clone();
430 while let Some(j) = clone.last() {
432 if matches!(j, Junction::Parachain(_) | Junction::GlobalConsensus(_)) {
433 return clone
435 } else {
436 (clone, _) = clone.split_last_interior();
437 }
438 }
439 Location::new(clone.parents, Junctions::Here)
440 }
441}
442
443impl Reanchorable for Location {
444 type Error = Self;
445
446 fn reanchor(&mut self, target: &Location, context: &InteriorLocation) -> Result<(), ()> {
451 let inverted_target = context.invert_target(target)?;
455
456 self.prepend_with(inverted_target).map_err(|_| ())?;
459
460 self.simplify(target.interior());
463
464 Ok(())
465 }
466
467 fn reanchored(mut self, target: &Location, context: &InteriorLocation) -> Result<Self, Self> {
472 match self.reanchor(target, context) {
473 Ok(()) => Ok(self),
474 Err(()) => Err(self),
475 }
476 }
477}
478
479impl TryFrom<OldLocation> for Option<Location> {
480 type Error = ();
481 fn try_from(value: OldLocation) -> result::Result<Self, Self::Error> {
482 Ok(Some(Location::try_from(value)?))
483 }
484}
485
486impl TryFrom<OldLocation> for Location {
487 type Error = ();
488 fn try_from(x: OldLocation) -> result::Result<Self, ()> {
489 Ok(Location { parents: x.parents, interior: x.interior.try_into()? })
490 }
491}
492
493impl TryFrom<NewLocation> for Option<Location> {
494 type Error = ();
495 fn try_from(new: NewLocation) -> result::Result<Self, Self::Error> {
496 Ok(Some(Location::try_from(new)?))
497 }
498}
499
500impl TryFrom<NewLocation> for Location {
501 type Error = ();
502 fn try_from(new: NewLocation) -> result::Result<Self, ()> {
503 Ok(Location { parents: new.parent_count(), interior: new.interior().clone().try_into()? })
504 }
505}
506
507#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
509pub struct Parent;
510impl From<Parent> for Location {
511 fn from(_: Parent) -> Self {
512 Location { parents: 1, interior: Junctions::Here }
513 }
514}
515
516#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
519pub struct ParentThen(pub Junctions);
520impl From<ParentThen> for Location {
521 fn from(ParentThen(interior): ParentThen) -> Self {
522 Location { parents: 1, interior }
523 }
524}
525
526#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
528pub struct Ancestor(pub u8);
529impl From<Ancestor> for Location {
530 fn from(Ancestor(parents): Ancestor) -> Self {
531 Location { parents, interior: Junctions::Here }
532 }
533}
534
535#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
538pub struct AncestorThen<Interior>(pub u8, pub Interior);
539impl<Interior: Into<Junctions>> From<AncestorThen<Interior>> for Location {
540 fn from(AncestorThen(parents, interior): AncestorThen<Interior>) -> Self {
541 Location { parents, interior: interior.into() }
542 }
543}
544
545impl From<[u8; 32]> for Location {
546 fn from(bytes: [u8; 32]) -> Self {
547 let junction: Junction = bytes.into();
548 junction.into()
549 }
550}
551
552impl From<sp_runtime::AccountId32> for Location {
553 fn from(id: sp_runtime::AccountId32) -> Self {
554 Junction::AccountId32 { network: None, id: id.into() }.into()
555 }
556}
557
558xcm_procedural::impl_conversion_functions_for_location_v4!();
559
560#[cfg(test)]
561mod tests {
562 use crate::v4::prelude::*;
563 use codec::{Decode, Encode};
564
565 #[test]
566 fn conversion_works() {
567 let x: Location = Parent.into();
568 assert_eq!(x, Location { parents: 1, interior: Here });
569 let x: Location = (Parent, Parent, OnlyChild).into();
574 assert_eq!(x, Location { parents: 2, interior: OnlyChild.into() });
575 let x: Location = OnlyChild.into();
576 assert_eq!(x, Location { parents: 0, interior: OnlyChild.into() });
577 let x: Location = (OnlyChild,).into();
578 assert_eq!(x, Location { parents: 0, interior: OnlyChild.into() });
579 }
580
581 #[test]
582 fn simplify_basic_works() {
583 let mut location: Location =
584 (Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into();
585 let context = [Parachain(1000), PalletInstance(42)].into();
586 let expected = GeneralIndex(69).into();
587 location.simplify(&context);
588 assert_eq!(location, expected);
589
590 let mut location: Location = (Parent, PalletInstance(42), GeneralIndex(69)).into();
591 let context = [PalletInstance(42)].into();
592 let expected = GeneralIndex(69).into();
593 location.simplify(&context);
594 assert_eq!(location, expected);
595
596 let mut location: Location = (Parent, PalletInstance(42), GeneralIndex(69)).into();
597 let context = [Parachain(1000), PalletInstance(42)].into();
598 let expected = GeneralIndex(69).into();
599 location.simplify(&context);
600 assert_eq!(location, expected);
601
602 let mut location: Location =
603 (Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into();
604 let context = [OnlyChild, Parachain(1000), PalletInstance(42)].into();
605 let expected = GeneralIndex(69).into();
606 location.simplify(&context);
607 assert_eq!(location, expected);
608 }
609
610 #[test]
611 fn simplify_incompatible_location_fails() {
612 let mut location: Location =
613 (Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into();
614 let context = [Parachain(1000), PalletInstance(42), GeneralIndex(42)].into();
615 let expected =
616 (Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into();
617 location.simplify(&context);
618 assert_eq!(location, expected);
619
620 let mut location: Location =
621 (Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into();
622 let context = [Parachain(1000)].into();
623 let expected =
624 (Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into();
625 location.simplify(&context);
626 assert_eq!(location, expected);
627 }
628
629 #[test]
630 fn reanchor_works() {
631 let mut id: Location = (Parent, Parachain(1000), GeneralIndex(42)).into();
632 let context = Parachain(2000).into();
633 let target = (Parent, Parachain(1000)).into();
634 let expected = GeneralIndex(42).into();
635 id.reanchor(&target, &context).unwrap();
636 assert_eq!(id, expected);
637 }
638
639 #[test]
640 fn encode_and_decode_works() {
641 let m = Location {
642 parents: 1,
643 interior: [Parachain(42), AccountIndex64 { network: None, index: 23 }].into(),
644 };
645 let encoded = m.encode();
646 assert_eq!(encoded, [1, 2, 0, 168, 2, 0, 92].to_vec());
647 let decoded = Location::decode(&mut &encoded[..]);
648 assert_eq!(decoded, Ok(m));
649 }
650
651 #[test]
652 fn match_and_split_works() {
653 let m = Location {
654 parents: 1,
655 interior: [Parachain(42), AccountIndex64 { network: None, index: 23 }].into(),
656 };
657 assert_eq!(m.match_and_split(&Location { parents: 1, interior: Here }), None);
658 assert_eq!(
659 m.match_and_split(&Location { parents: 1, interior: [Parachain(42)].into() }),
660 Some(&AccountIndex64 { network: None, index: 23 })
661 );
662 assert_eq!(m.match_and_split(&m), None);
663 }
664
665 #[test]
666 fn append_with_works() {
667 let acc = AccountIndex64 { network: None, index: 23 };
668 let mut m = Location { parents: 1, interior: [Parachain(42)].into() };
669 assert_eq!(m.append_with([PalletInstance(3), acc]), Ok(()));
670 assert_eq!(
671 m,
672 Location { parents: 1, interior: [Parachain(42), PalletInstance(3), acc].into() }
673 );
674
675 let acc = AccountIndex64 { network: None, index: 23 };
677 let m = Location {
678 parents: 254,
679 interior: [Parachain(42), OnlyChild, OnlyChild, OnlyChild, OnlyChild].into(),
680 };
681 let suffix: Location = (PalletInstance(3), acc, OnlyChild, OnlyChild).into();
682 assert_eq!(m.clone().append_with(suffix.clone()), Err(suffix));
683 }
684
685 #[test]
686 fn prepend_with_works() {
687 let mut m = Location {
688 parents: 1,
689 interior: [Parachain(42), AccountIndex64 { network: None, index: 23 }].into(),
690 };
691 assert_eq!(m.prepend_with(Location { parents: 1, interior: [OnlyChild].into() }), Ok(()));
692 assert_eq!(
693 m,
694 Location {
695 parents: 1,
696 interior: [Parachain(42), AccountIndex64 { network: None, index: 23 }].into()
697 }
698 );
699
700 let mut m = Location { parents: 254, interior: [Parachain(42)].into() };
702 let prefix = Location { parents: 2, interior: Here };
703 assert_eq!(m.prepend_with(prefix.clone()), Err(prefix));
704
705 let prefix = Location { parents: 1, interior: Here };
706 assert_eq!(m.prepend_with(prefix.clone()), Ok(()));
707 assert_eq!(m, Location { parents: 255, interior: [Parachain(42)].into() });
708 }
709
710 #[test]
711 fn double_ended_ref_iteration_works() {
712 let m: Junctions = [Parachain(1000), Parachain(3), PalletInstance(5)].into();
713 let mut iter = m.iter();
714
715 let first = iter.next().unwrap();
716 assert_eq!(first, &Parachain(1000));
717 let third = iter.next_back().unwrap();
718 assert_eq!(third, &PalletInstance(5));
719 let second = iter.next_back().unwrap();
720 assert_eq!(iter.next(), None);
721 assert_eq!(iter.next_back(), None);
722 assert_eq!(second, &Parachain(3));
723
724 let res = Here
725 .pushed_with(*first)
726 .unwrap()
727 .pushed_with(*second)
728 .unwrap()
729 .pushed_with(*third)
730 .unwrap();
731 assert_eq!(m, res);
732
733 let m = Here;
735 let mut iter = m.iter();
736
737 assert_eq!(iter.next(), None);
738 assert_eq!(iter.next_back(), None);
739 }
740
741 #[test]
742 fn conversion_from_other_types_works() {
743 use crate::v3;
744
745 fn takes_location<Arg: Into<Location>>(_arg: Arg) {}
746
747 takes_location(Parent);
748 takes_location(Here);
749 takes_location([Parachain(42)]);
750 takes_location((Ancestor(255), PalletInstance(8)));
751 takes_location((Ancestor(5), Parachain(1), PalletInstance(3)));
752 takes_location((Ancestor(2), Here));
753 takes_location(AncestorThen(
754 3,
755 [Parachain(43), AccountIndex64 { network: None, index: 155 }],
756 ));
757 takes_location((Parent, AccountId32 { network: None, id: [0; 32] }));
758 takes_location((Parent, Here));
759 takes_location(ParentThen([Parachain(75)].into()));
760 takes_location([Parachain(100), PalletInstance(3)]);
761
762 assert_eq!(v3::Location::from(v3::Junctions::Here).try_into(), Ok(Location::here()));
763 assert_eq!(v3::Location::from(v3::Parent).try_into(), Ok(Location::parent()));
764 assert_eq!(
765 v3::Location::from((v3::Parent, v3::Parent, v3::Junction::GeneralIndex(42u128),))
766 .try_into(),
767 Ok(Location { parents: 2, interior: [GeneralIndex(42u128)].into() }),
768 );
769 }
770}