1use super::{Junction, Location, NetworkId};
20use alloc::sync::Arc;
21use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
22use core::{mem, ops::Range, result};
23use scale_info::TypeInfo;
24
25pub(crate) const MAX_JUNCTIONS: usize = 8;
27
28#[derive(
34 Clone,
35 Eq,
36 PartialEq,
37 Ord,
38 PartialOrd,
39 Encode,
40 Decode,
41 DecodeWithMemTracking,
42 Debug,
43 TypeInfo,
44 MaxEncodedLen,
45 serde::Serialize,
46 serde::Deserialize,
47)]
48pub enum Junctions {
49 Here,
51 X1(Arc<[Junction; 1]>),
53 X2(Arc<[Junction; 2]>),
55 X3(Arc<[Junction; 3]>),
57 X4(Arc<[Junction; 4]>),
59 X5(Arc<[Junction; 5]>),
61 X6(Arc<[Junction; 6]>),
63 X7(Arc<[Junction; 7]>),
65 X8(Arc<[Junction; 8]>),
67}
68
69macro_rules! impl_junctions {
70 ($count:expr, $variant:ident) => {
71 impl From<[Junction; $count]> for Junctions {
72 fn from(junctions: [Junction; $count]) -> Self {
73 Self::$variant(Arc::new(junctions))
74 }
75 }
76 impl PartialEq<[Junction; $count]> for Junctions {
77 fn eq(&self, rhs: &[Junction; $count]) -> bool {
78 self.as_slice() == rhs
79 }
80 }
81 };
82}
83
84impl_junctions!(1, X1);
85impl_junctions!(2, X2);
86impl_junctions!(3, X3);
87impl_junctions!(4, X4);
88impl_junctions!(5, X5);
89impl_junctions!(6, X6);
90impl_junctions!(7, X7);
91impl_junctions!(8, X8);
92
93pub struct JunctionsIterator {
94 junctions: Junctions,
95 range: Range<usize>,
96}
97
98impl Iterator for JunctionsIterator {
99 type Item = Junction;
100 fn next(&mut self) -> Option<Junction> {
101 self.junctions.at(self.range.next()?).cloned()
102 }
103}
104
105impl DoubleEndedIterator for JunctionsIterator {
106 fn next_back(&mut self) -> Option<Junction> {
107 self.junctions.at(self.range.next_back()?).cloned()
108 }
109}
110
111pub struct JunctionsRefIterator<'a> {
112 junctions: &'a Junctions,
113 range: Range<usize>,
114}
115
116impl<'a> Iterator for JunctionsRefIterator<'a> {
117 type Item = &'a Junction;
118 fn next(&mut self) -> Option<&'a Junction> {
119 self.junctions.at(self.range.next()?)
120 }
121}
122
123impl<'a> DoubleEndedIterator for JunctionsRefIterator<'a> {
124 fn next_back(&mut self) -> Option<&'a Junction> {
125 self.junctions.at(self.range.next_back()?)
126 }
127}
128impl<'a> IntoIterator for &'a Junctions {
129 type Item = &'a Junction;
130 type IntoIter = JunctionsRefIterator<'a>;
131 fn into_iter(self) -> Self::IntoIter {
132 JunctionsRefIterator { junctions: self, range: 0..self.len() }
133 }
134}
135
136impl IntoIterator for Junctions {
137 type Item = Junction;
138 type IntoIter = JunctionsIterator;
139 fn into_iter(self) -> Self::IntoIter {
140 JunctionsIterator { range: 0..self.len(), junctions: self }
141 }
142}
143
144impl Junctions {
145 pub const fn into_location(self) -> Location {
149 Location { parents: 0, interior: self }
150 }
151
152 pub const fn into_exterior(self, n: u8) -> Location {
157 Location { parents: n, interior: self }
158 }
159
160 pub fn as_slice(&self) -> &[Junction] {
162 match self {
163 Junctions::Here => &[],
164 Junctions::X1(ref a) => &a[..],
165 Junctions::X2(ref a) => &a[..],
166 Junctions::X3(ref a) => &a[..],
167 Junctions::X4(ref a) => &a[..],
168 Junctions::X5(ref a) => &a[..],
169 Junctions::X6(ref a) => &a[..],
170 Junctions::X7(ref a) => &a[..],
171 Junctions::X8(ref a) => &a[..],
172 }
173 }
174
175 pub fn as_slice_mut(&mut self) -> &mut [Junction] {
177 match self {
178 Junctions::Here => &mut [],
179 Junctions::X1(ref mut a) => &mut Arc::make_mut(a)[..],
180 Junctions::X2(ref mut a) => &mut Arc::make_mut(a)[..],
181 Junctions::X3(ref mut a) => &mut Arc::make_mut(a)[..],
182 Junctions::X4(ref mut a) => &mut Arc::make_mut(a)[..],
183 Junctions::X5(ref mut a) => &mut Arc::make_mut(a)[..],
184 Junctions::X6(ref mut a) => &mut Arc::make_mut(a)[..],
185 Junctions::X7(ref mut a) => &mut Arc::make_mut(a)[..],
186 Junctions::X8(ref mut a) => &mut Arc::make_mut(a)[..],
187 }
188 }
189
190 pub fn remove_network_id(&mut self) {
192 self.for_each_mut(Junction::remove_network_id);
193 }
194
195 pub fn invert_target(&self, target: &Location) -> Result<Location, ()> {
198 let mut itself = self.clone();
199 let mut junctions = Self::Here;
200 for _ in 0..target.parent_count() {
201 junctions = junctions
202 .pushed_front_with(itself.take_last().unwrap_or(Junction::OnlyChild))
203 .map_err(|_| ())?;
204 }
205 let parents = target.interior().len() as u8;
206 Ok(Location::new(parents, junctions))
207 }
208
209 pub fn for_each_mut(&mut self, x: impl FnMut(&mut Junction)) {
212 self.as_slice_mut().iter_mut().for_each(x)
213 }
214
215 pub fn global_consensus(&self) -> Result<NetworkId, ()> {
220 if let Some(Junction::GlobalConsensus(network)) = self.first() {
221 Ok(*network)
222 } else {
223 Err(())
224 }
225 }
226
227 pub fn split_global(self) -> Result<(NetworkId, Junctions), ()> {
233 match self.split_first() {
234 (location, Some(Junction::GlobalConsensus(network))) => Ok((network, location)),
235 _ => return Err(()),
236 }
237 }
238
239 pub fn within_global(mut self, relative: Location) -> Result<Self, ()> {
245 if self.len() <= relative.parent_count() as usize {
246 return Err(())
247 }
248 for _ in 0..relative.parent_count() {
249 self.take_last();
250 }
251 for j in relative.interior() {
252 self.push(*j).map_err(|_| ())?;
253 }
254 Ok(self)
255 }
256
257 pub fn relative_to(mut self, viewer: &Junctions) -> Location {
259 let mut i = 0;
260 while match (self.first(), viewer.at(i)) {
261 (Some(x), Some(y)) => x == y,
262 _ => false,
263 } {
264 self = self.split_first().0;
265 i += 1;
267 }
268 Location::new((viewer.len() - i) as u8, self)
272 }
273
274 pub fn first(&self) -> Option<&Junction> {
276 self.as_slice().first()
277 }
278
279 pub fn last(&self) -> Option<&Junction> {
281 self.as_slice().last()
282 }
283
284 pub fn split_first(self) -> (Junctions, Option<Junction>) {
287 match self {
288 Junctions::Here => (Junctions::Here, None),
289 Junctions::X1(xs) => {
290 let [a] = *xs;
291 (Junctions::Here, Some(a))
292 },
293 Junctions::X2(xs) => {
294 let [a, b] = *xs;
295 ([b].into(), Some(a))
296 },
297 Junctions::X3(xs) => {
298 let [a, b, c] = *xs;
299 ([b, c].into(), Some(a))
300 },
301 Junctions::X4(xs) => {
302 let [a, b, c, d] = *xs;
303 ([b, c, d].into(), Some(a))
304 },
305 Junctions::X5(xs) => {
306 let [a, b, c, d, e] = *xs;
307 ([b, c, d, e].into(), Some(a))
308 },
309 Junctions::X6(xs) => {
310 let [a, b, c, d, e, f] = *xs;
311 ([b, c, d, e, f].into(), Some(a))
312 },
313 Junctions::X7(xs) => {
314 let [a, b, c, d, e, f, g] = *xs;
315 ([b, c, d, e, f, g].into(), Some(a))
316 },
317 Junctions::X8(xs) => {
318 let [a, b, c, d, e, f, g, h] = *xs;
319 ([b, c, d, e, f, g, h].into(), Some(a))
320 },
321 }
322 }
323
324 pub fn split_last(self) -> (Junctions, Option<Junction>) {
327 match self {
328 Junctions::Here => (Junctions::Here, None),
329 Junctions::X1(xs) => {
330 let [a] = *xs;
331 (Junctions::Here, Some(a))
332 },
333 Junctions::X2(xs) => {
334 let [a, b] = *xs;
335 ([a].into(), Some(b))
336 },
337 Junctions::X3(xs) => {
338 let [a, b, c] = *xs;
339 ([a, b].into(), Some(c))
340 },
341 Junctions::X4(xs) => {
342 let [a, b, c, d] = *xs;
343 ([a, b, c].into(), Some(d))
344 },
345 Junctions::X5(xs) => {
346 let [a, b, c, d, e] = *xs;
347 ([a, b, c, d].into(), Some(e))
348 },
349 Junctions::X6(xs) => {
350 let [a, b, c, d, e, f] = *xs;
351 ([a, b, c, d, e].into(), Some(f))
352 },
353 Junctions::X7(xs) => {
354 let [a, b, c, d, e, f, g] = *xs;
355 ([a, b, c, d, e, f].into(), Some(g))
356 },
357 Junctions::X8(xs) => {
358 let [a, b, c, d, e, f, g, h] = *xs;
359 ([a, b, c, d, e, f, g].into(), Some(h))
360 },
361 }
362 }
363
364 pub fn take_first(&mut self) -> Option<Junction> {
366 let mut d = Junctions::Here;
367 mem::swap(&mut *self, &mut d);
368 let (tail, head) = d.split_first();
369 *self = tail;
370 head
371 }
372
373 pub fn take_last(&mut self) -> Option<Junction> {
375 let mut d = Junctions::Here;
376 mem::swap(&mut *self, &mut d);
377 let (head, tail) = d.split_last();
378 *self = head;
379 tail
380 }
381
382 pub fn push(&mut self, new: impl Into<Junction>) -> result::Result<(), Junction> {
384 let new = new.into();
385 let mut dummy = Junctions::Here;
386 mem::swap(self, &mut dummy);
387 match dummy.pushed_with(new) {
388 Ok(s) => {
389 *self = s;
390 Ok(())
391 },
392 Err((s, j)) => {
393 *self = s;
394 Err(j)
395 },
396 }
397 }
398
399 pub fn push_front(&mut self, new: impl Into<Junction>) -> result::Result<(), Junction> {
401 let new = new.into();
402 let mut dummy = Junctions::Here;
403 mem::swap(self, &mut dummy);
404 match dummy.pushed_front_with(new) {
405 Ok(s) => {
406 *self = s;
407 Ok(())
408 },
409 Err((s, j)) => {
410 *self = s;
411 Err(j)
412 },
413 }
414 }
415
416 pub fn pushed_with(self, new: impl Into<Junction>) -> result::Result<Self, (Self, Junction)> {
419 let new = new.into();
420 Ok(match self {
421 Junctions::Here => [new].into(),
422 Junctions::X1(xs) => {
423 let [a] = *xs;
424 [a, new].into()
425 },
426 Junctions::X2(xs) => {
427 let [a, b] = *xs;
428 [a, b, new].into()
429 },
430 Junctions::X3(xs) => {
431 let [a, b, c] = *xs;
432 [a, b, c, new].into()
433 },
434 Junctions::X4(xs) => {
435 let [a, b, c, d] = *xs;
436 [a, b, c, d, new].into()
437 },
438 Junctions::X5(xs) => {
439 let [a, b, c, d, e] = *xs;
440 [a, b, c, d, e, new].into()
441 },
442 Junctions::X6(xs) => {
443 let [a, b, c, d, e, f] = *xs;
444 [a, b, c, d, e, f, new].into()
445 },
446 Junctions::X7(xs) => {
447 let [a, b, c, d, e, f, g] = *xs;
448 [a, b, c, d, e, f, g, new].into()
449 },
450 s => Err((s, new))?,
451 })
452 }
453
454 pub fn pushed_front_with(
457 self,
458 new: impl Into<Junction>,
459 ) -> result::Result<Self, (Self, Junction)> {
460 let new = new.into();
461 Ok(match self {
462 Junctions::Here => [new].into(),
463 Junctions::X1(xs) => {
464 let [a] = *xs;
465 [new, a].into()
466 },
467 Junctions::X2(xs) => {
468 let [a, b] = *xs;
469 [new, a, b].into()
470 },
471 Junctions::X3(xs) => {
472 let [a, b, c] = *xs;
473 [new, a, b, c].into()
474 },
475 Junctions::X4(xs) => {
476 let [a, b, c, d] = *xs;
477 [new, a, b, c, d].into()
478 },
479 Junctions::X5(xs) => {
480 let [a, b, c, d, e] = *xs;
481 [new, a, b, c, d, e].into()
482 },
483 Junctions::X6(xs) => {
484 let [a, b, c, d, e, f] = *xs;
485 [new, a, b, c, d, e, f].into()
486 },
487 Junctions::X7(xs) => {
488 let [a, b, c, d, e, f, g] = *xs;
489 [new, a, b, c, d, e, f, g].into()
490 },
491 s => Err((s, new))?,
492 })
493 }
494
495 pub fn append_with(&mut self, suffix: impl Into<Junctions>) -> Result<(), Junctions> {
509 let suffix = suffix.into();
510 if self.len().saturating_add(suffix.len()) > MAX_JUNCTIONS {
511 return Err(suffix)
512 }
513 for j in suffix.into_iter() {
514 self.push(j).expect("Already checked the sum of the len()s; qed")
515 }
516 Ok(())
517 }
518
519 pub fn len(&self) -> usize {
521 self.as_slice().len()
522 }
523
524 pub fn at(&self, i: usize) -> Option<&Junction> {
527 self.as_slice().get(i)
528 }
529
530 pub fn at_mut(&mut self, i: usize) -> Option<&mut Junction> {
533 self.as_slice_mut().get_mut(i)
534 }
535
536 pub fn iter(&self) -> JunctionsRefIterator {
538 JunctionsRefIterator { junctions: self, range: 0..self.len() }
539 }
540
541 pub fn match_and_split(&self, prefix: &Junctions) -> Option<&Junction> {
554 if prefix.len() + 1 != self.len() {
555 return None
556 }
557 for i in 0..prefix.len() {
558 if prefix.at(i) != self.at(i) {
559 return None
560 }
561 }
562 return self.at(prefix.len())
563 }
564
565 pub fn starts_with(&self, prefix: &Junctions) -> bool {
566 prefix.len() <= self.len() && prefix.iter().zip(self.iter()).all(|(x, y)| x == y)
567 }
568}
569
570impl TryFrom<Location> for Junctions {
571 type Error = Location;
572 fn try_from(x: Location) -> result::Result<Self, Location> {
573 if x.parent_count() > 0 {
574 Err(x)
575 } else {
576 Ok(x.interior().clone())
577 }
578 }
579}
580
581impl<T: Into<Junction>> From<T> for Junctions {
582 fn from(x: T) -> Self {
583 [x.into()].into()
584 }
585}
586
587impl From<[Junction; 0]> for Junctions {
588 fn from(_: [Junction; 0]) -> Self {
589 Self::Here
590 }
591}
592
593impl From<()> for Junctions {
594 fn from(_: ()) -> Self {
595 Self::Here
596 }
597}
598
599xcm_procedural::impl_conversion_functions_for_junctions_v5!();
600
601#[cfg(test)]
602mod tests {
603 use super::{super::prelude::*, *};
604
605 #[test]
606 fn inverting_works() {
607 let context: InteriorLocation = (Parachain(1000), PalletInstance(42)).into();
608 let target = (Parent, PalletInstance(69)).into();
609 let expected = (Parent, PalletInstance(42)).into();
610 let inverted = context.invert_target(&target).unwrap();
611 assert_eq!(inverted, expected);
612
613 let context: InteriorLocation =
614 (Parachain(1000), PalletInstance(42), GeneralIndex(1)).into();
615 let target = (Parent, Parent, PalletInstance(69), GeneralIndex(2)).into();
616 let expected = (Parent, Parent, PalletInstance(42), GeneralIndex(1)).into();
617 let inverted = context.invert_target(&target).unwrap();
618 assert_eq!(inverted, expected);
619 }
620
621 #[test]
622 fn relative_to_works() {
623 use NetworkId::*;
624 assert_eq!(
625 Junctions::from([Polkadot.into()]).relative_to(&Junctions::from([Kusama.into()])),
626 (Parent, Polkadot).into()
627 );
628 let base = Junctions::from([Kusama.into(), Parachain(1), PalletInstance(1)]);
629
630 assert_eq!(Here.relative_to(&base), (Parent, Parent, Parent).into());
632 assert_eq!(Junctions::from([Kusama.into()]).relative_to(&base), (Parent, Parent).into());
633 assert_eq!(
634 Junctions::from([Kusama.into(), Parachain(1)]).relative_to(&base),
635 (Parent,).into()
636 );
637 assert_eq!(
638 Junctions::from([Kusama.into(), Parachain(1), PalletInstance(1)]).relative_to(&base),
639 Here.into()
640 );
641
642 assert_eq!(
644 Junctions::from([Polkadot.into()]).relative_to(&base),
645 (Parent, Parent, Parent, Polkadot).into()
646 );
647 assert_eq!(
648 Junctions::from([Kusama.into(), Parachain(2)]).relative_to(&base),
649 (Parent, Parent, Parachain(2)).into()
650 );
651 assert_eq!(
652 Junctions::from([Kusama.into(), Parachain(1), PalletInstance(2)]).relative_to(&base),
653 (Parent, PalletInstance(2)).into()
654 );
655 assert_eq!(
656 Junctions::from([Kusama.into(), Parachain(1), PalletInstance(1), [1u8; 32].into()])
657 .relative_to(&base),
658 ([1u8; 32],).into()
659 );
660
661 assert_eq!(
663 Junctions::from([Polkadot.into(), Parachain(1)]).relative_to(&base),
664 (Parent, Parent, Parent, Polkadot, Parachain(1)).into()
665 );
666 assert_eq!(
667 Junctions::from([Kusama.into(), Parachain(2), PalletInstance(1)]).relative_to(&base),
668 (Parent, Parent, Parachain(2), PalletInstance(1)).into()
669 );
670 assert_eq!(
671 Junctions::from([Kusama.into(), Parachain(1), PalletInstance(2), [1u8; 32].into()])
672 .relative_to(&base),
673 (Parent, PalletInstance(2), [1u8; 32]).into()
674 );
675 assert_eq!(
676 Junctions::from([
677 Kusama.into(),
678 Parachain(1),
679 PalletInstance(1),
680 [1u8; 32].into(),
681 1u128.into()
682 ])
683 .relative_to(&base),
684 ([1u8; 32], 1u128).into()
685 );
686 }
687
688 #[test]
689 fn global_consensus_works() {
690 use NetworkId::*;
691 assert_eq!(Junctions::from([Polkadot.into()]).global_consensus(), Ok(Polkadot));
692 assert_eq!(Junctions::from([Kusama.into(), 1u64.into()]).global_consensus(), Ok(Kusama));
693 assert_eq!(Here.global_consensus(), Err(()));
694 assert_eq!(Junctions::from([1u64.into()]).global_consensus(), Err(()));
695 assert_eq!(Junctions::from([1u64.into(), Kusama.into()]).global_consensus(), Err(()));
696 }
697
698 #[test]
699 fn test_conversion() {
700 use super::{Junction::*, NetworkId::*};
701 let x: Junctions = GlobalConsensus(Polkadot).into();
702 assert_eq!(x, Junctions::from([GlobalConsensus(Polkadot)]));
703 let x: Junctions = Polkadot.into();
704 assert_eq!(x, Junctions::from([GlobalConsensus(Polkadot)]));
705 let x: Junctions = (Polkadot, Kusama).into();
706 assert_eq!(x, Junctions::from([GlobalConsensus(Polkadot), GlobalConsensus(Kusama)]));
707 }
708
709 #[test]
710 fn encode_decode_junctions_works() {
711 let original = Junctions::from([
712 Polkadot.into(),
713 Kusama.into(),
714 1u64.into(),
715 GlobalConsensus(Polkadot),
716 Parachain(123),
717 PalletInstance(45),
718 ]);
719 let encoded = original.encode();
720 assert_eq!(encoded, &[6, 9, 2, 9, 3, 2, 0, 4, 9, 2, 0, 237, 1, 4, 45]);
721 let decoded = Junctions::decode(&mut &encoded[..]).unwrap();
722 assert_eq!(decoded, original);
723 }
724}