Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Add starts_with to v0 and v1 MultiLocation #6311

Merged
merged 3 commits into from
Nov 20, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions xcm/src/v0/multi_location.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,17 +356,30 @@ impl MultiLocation {
/// # }
/// ```
pub fn match_and_split(&self, prefix: &MultiLocation) -> Option<&Junction> {
if prefix.len() + 1 != self.len() {
if prefix.len() + 1 != self.len() || !self.starts_with(prefix) {
return None
}
for i in 0..prefix.len() {
if prefix.at(i) != self.at(i) {
return None
}
}
return self.at(prefix.len())
}

/// Returns whether `self` begins with or is equal to `prefix`.
///
/// # Example
/// ```rust
/// # use xcm::v0::{Junction::*, MultiLocation::*};
/// let m = X4(Parent, PalletInstance(3), OnlyChild, OnlyChild);
/// assert!(m.starts_with(&X2(Parent, PalletInstance(3))));
/// assert!(m.starts_with(&m));
/// assert!(!m.starts_with(&X2(Parent, GeneralIndex(99))));
/// assert!(!m.starts_with(&X1(PalletInstance(3))));
/// ```
pub fn starts_with(&self, prefix: &MultiLocation) -> bool {
if self.len() < prefix.len() {
return false
}
prefix.iter().zip(self.iter()).all(|(l, r)| l == r)
}

/// Mutates `self`, suffixing it with `new`. Returns `Err` in case of overflow.
pub fn push(&mut self, new: Junction) -> result::Result<(), ()> {
let mut n = MultiLocation::Null;
Expand Down
44 changes: 38 additions & 6 deletions xcm/src/v1/multilocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,24 @@ impl MultiLocation {
self.interior.match_and_split(&prefix.interior)
}

/// Returns whether `self` has the same number of parents as `prefix` and its junctions begins
/// with the junctions of `prefix`.
///
/// # Example
/// ```rust
/// # use xcm::v1::{Junctions::*, Junction::*, MultiLocation};
/// let m = MultiLocation::new(1, X3(PalletInstance(3), OnlyChild, OnlyChild));
/// assert!(m.starts_with(&MultiLocation::new(1, X1(PalletInstance(3)))));
/// assert!(!m.starts_with(&MultiLocation::new(1, X1(GeneralIndex(99)))));
/// assert!(!m.starts_with(&MultiLocation::new(0, X1(PalletInstance(3)))));
/// ```
pub fn starts_with(&self, prefix: &MultiLocation) -> bool {
if self.parents != prefix.parents {
return false
}
self.interior.starts_with(&prefix.interior)
}

/// Mutate `self` so that it is suffixed with `suffix`.
///
/// Does not modify `self` and returns `Err` with `suffix` in case of overflow.
Expand Down Expand Up @@ -801,15 +819,29 @@ impl Junctions {
/// # }
/// ```
pub fn match_and_split(&self, prefix: &Junctions) -> Option<&Junction> {
if prefix.len() + 1 != self.len() {
if prefix.len() + 1 != self.len() || !self.starts_with(prefix) {
return None
}
for i in 0..prefix.len() {
if prefix.at(i) != self.at(i) {
return None
}
self.at(prefix.len())
}

/// Returns whether `self` begins with or is equal to `prefix`.
///
/// # Example
/// ```rust
/// # use xcm::v1::{Junctions::*, Junction::*};
/// let mut j = X3(Parachain(2), PalletInstance(3), OnlyChild);
/// assert!(j.starts_with(&X2(Parachain(2), PalletInstance(3))));
/// assert!(j.starts_with(&j));
/// assert!(j.starts_with(&X1(Parachain(2))));
/// assert!(!j.starts_with(&X1(Parachain(999))));
/// assert!(!j.starts_with(&X4(Parachain(2), PalletInstance(3), OnlyChild, OnlyChild)));
/// ```
pub fn starts_with(&self, prefix: &Junctions) -> bool {
if self.len() < prefix.len() {
return false
}
return self.at(prefix.len())
prefix.iter().zip(self.iter()).all(|(l, r)| l == r)
}
}

Expand Down