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