#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(
feature = "scale",
derive(
scale_info::TypeInfo,
scale_codec::Encode,
scale_codec::Decode,
scale_codec::MaxEncodedLen
)
)]
pub enum TargetSystem {
ContractAddress([u8; 20]),
Substrate(SubstrateTargetSystem),
}
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Hash, typed_builder::TypedBuilder,
)]
#[cfg_attr(
feature = "scale",
derive(
scale_info::TypeInfo,
scale_codec::Encode,
scale_codec::Decode,
scale_codec::MaxEncodedLen
)
)]
pub struct SubstrateTargetSystem {
pub pallet_index: u8,
pub tree_id: u32,
}
impl TargetSystem {
pub const LENGTH: usize = 26;
#[must_use]
pub fn new_contract_address<T: Into<[u8; 20]>>(address: T) -> Self {
let bytes = address.into();
Self::ContractAddress(bytes)
}
#[must_use]
pub fn to_bytes(&self) -> [u8; Self::LENGTH] {
match self {
TargetSystem::ContractAddress(address) => {
let mut bytes = [0u8; TargetSystem::LENGTH];
let f = 6usize;
let t = f + 20;
bytes[f..t].copy_from_slice(address);
bytes
}
TargetSystem::Substrate(target_system) => {
let mut bytes = [0u8; TargetSystem::LENGTH];
let f = 22usize;
let t = f + core::mem::size_of::<u32>();
bytes[f - 1] = target_system.pallet_index;
bytes[f..t]
.copy_from_slice(&target_system.tree_id.to_be_bytes());
bytes
}
}
}
#[must_use]
pub fn into_bytes(self) -> [u8; Self::LENGTH] {
self.to_bytes()
}
#[must_use]
pub fn get_substrate_target_system(self) -> Option<SubstrateTargetSystem> {
match self {
TargetSystem::Substrate(target_system) => Some(target_system),
_ => None,
}
}
#[must_use]
pub fn into_contract_address_or_default(self) -> [u8; 20] {
match self {
TargetSystem::ContractAddress(address) => address,
_ => [0; 20],
}
}
}
impl From<[u8; TargetSystem::LENGTH]> for TargetSystem {
fn from(bytes: [u8; TargetSystem::LENGTH]) -> Self {
if bytes[0..20].iter().all(|&x| x == 0) {
let mut tree_id_bytes = [0u8; 4];
let f = 22usize;
let t = f + core::mem::size_of::<u32>();
tree_id_bytes.copy_from_slice(&bytes[f..t]);
let tree_id = u32::from_be_bytes(tree_id_bytes);
let target = SubstrateTargetSystem::builder()
.pallet_index(bytes[f - 1])
.tree_id(tree_id)
.build();
TargetSystem::Substrate(target)
} else {
let mut address_bytes = [0u8; 20];
let f = 6usize;
let t = f + 20;
address_bytes.copy_from_slice(&bytes[f..t]);
TargetSystem::ContractAddress(address_bytes)
}
}
}
impl From<TargetSystem> for [u8; TargetSystem::LENGTH] {
fn from(target_system: TargetSystem) -> Self {
target_system.into_bytes()
}
}
impl Default for TargetSystem {
fn default() -> Self {
let target = SubstrateTargetSystem::builder()
.pallet_index(0)
.tree_id(0)
.build();
TargetSystem::Substrate(target)
}
}