use crate::{HasHeader, types::metadata::StringOrBytes};
use codec::{Decode, Encode};
pub trait TransactionEventEncodable {
fn to_event(&self) -> Vec<u8>;
}
pub trait TransactionEventDecodable: Sized {
fn from_event<'a>(event: impl Into<StringOrBytes<'a>>) -> Result<Self, String>;
}
impl<T: HasHeader + Encode> TransactionEventEncodable for T {
fn to_event(&self) -> Vec<u8> {
let pallet_id = Self::HEADER_INDEX.0;
let variant_id = Self::HEADER_INDEX.1;
let mut encoded_event: Vec<u8> = vec![pallet_id, variant_id];
Self::encode_to(self, &mut encoded_event);
encoded_event
}
}
impl<T: HasHeader + Decode> TransactionEventDecodable for T {
fn from_event<'a>(event: impl Into<StringOrBytes<'a>>) -> Result<Self, String> {
fn inner<T: HasHeader + Decode>(event: StringOrBytes) -> Result<T, String> {
let event: &[u8] = match &event {
StringOrBytes::StringRef(s) => {
&const_hex::decode(s.trim_start_matches("0x")).map_err(|x| x.to_string())?
},
StringOrBytes::BoxedString(s) => {
&const_hex::decode(s.trim_start_matches("0x")).map_err(|x| x.to_string())?
},
StringOrBytes::Bytes(b) => b,
StringOrBytes::BoxedBytes(b) => b,
};
check_header(event, T::HEADER_INDEX)?;
let mut data = if event.len() <= 2 { &[] } else { &event[2..] };
Ok(T::decode(&mut data).map_err(|x| x.to_string())?)
}
inner(event.into())
}
}
pub(crate) fn check_header(data: &[u8], header_index: (u8, u8)) -> Result<(), String> {
if data.len() < 2 {
return Err("Failed to decode. Not have enough bytes to decode the header".into());
}
let (pallet_id, variant_id) = (data[0], data[1]);
if header_index.0 != pallet_id || header_index.1 != variant_id {
let err = std::format!(
"Failed to decode. Mismatch in pallet and/or variant id. Actual: PI: {}, VI: {} Expected: PI: {}, VI: {}",
pallet_id,
variant_id,
header_index.0,
header_index.1
);
return Err(err);
}
Ok(())
}