use core::marker::PhantomData;
use derive_where::derive_where;
use frame_decode::runtime_apis::IntoEncodableValues;
use scale_decode::DecodeAsType;
use std::borrow::Cow;
pub trait Payload {
type ArgsType: IntoEncodableValues;
type ReturnType: DecodeAsType;
fn trait_name(&self) -> &str;
fn method_name(&self) -> &str;
fn args(&self) -> &Self::ArgsType;
fn validation_hash(&self) -> Option<[u8; 32]> {
None
}
}
impl<P: Payload + ?Sized> Payload for &'_ P {
type ArgsType = P::ArgsType;
type ReturnType = P::ReturnType;
fn trait_name(&self) -> &str {
P::trait_name(*self)
}
fn method_name(&self) -> &str {
P::method_name(*self)
}
fn args(&self) -> &Self::ArgsType {
P::args(*self)
}
fn validation_hash(&self) -> Option<[u8; 32]> {
P::validation_hash(*self)
}
}
#[derive_where(Clone, Debug, Eq, Ord, PartialEq, PartialOrd; ArgsType)]
pub struct StaticPayload<ArgsType, ReturnType> {
trait_name: Cow<'static, str>,
method_name: Cow<'static, str>,
args: ArgsType,
validation_hash: Option<[u8; 32]>,
_marker: PhantomData<ReturnType>,
}
pub type DynamicPayload<ArgsType, ReturnType> = StaticPayload<ArgsType, ReturnType>;
impl<ArgsType: IntoEncodableValues, ReturnType: DecodeAsType> Payload
for StaticPayload<ArgsType, ReturnType>
{
type ArgsType = ArgsType;
type ReturnType = ReturnType;
fn trait_name(&self) -> &str {
&self.trait_name
}
fn method_name(&self) -> &str {
&self.method_name
}
fn args(&self) -> &Self::ArgsType {
&self.args
}
fn validation_hash(&self) -> Option<[u8; 32]> {
self.validation_hash
}
}
impl<ArgsType, ReturnTy> StaticPayload<ArgsType, ReturnTy> {
pub fn new(
trait_name: impl Into<String>,
method_name: impl Into<String>,
args: ArgsType,
) -> Self {
StaticPayload {
trait_name: trait_name.into().into(),
method_name: method_name.into().into(),
args,
validation_hash: None,
_marker: PhantomData,
}
}
#[doc(hidden)]
pub fn new_static(
trait_name: &'static str,
method_name: &'static str,
args: ArgsType,
hash: [u8; 32],
) -> StaticPayload<ArgsType, ReturnTy> {
StaticPayload {
trait_name: Cow::Borrowed(trait_name),
method_name: Cow::Borrowed(method_name),
args,
validation_hash: Some(hash),
_marker: core::marker::PhantomData,
}
}
pub fn unvalidated(self) -> Self {
Self {
validation_hash: None,
..self
}
}
pub fn trait_name(&self) -> &str {
&self.trait_name
}
pub fn method_name(&self) -> &str {
&self.method_name
}
}
pub fn dynamic<ArgsType, ReturnType>(
trait_name: impl Into<String>,
method_name: impl Into<String>,
args_data: ArgsType,
) -> DynamicPayload<ArgsType, ReturnType> {
DynamicPayload::new(trait_name, method_name, args_data)
}