use crate::ReceiveAuthHandles;
use crate::xdr::ReadXDR;
#[diagnostic::on_unimplemented(
message = "`&{Self}` cannot be a `#[contract]` method parameter",
label = "no `RefArg` impl for `{Self}`",
note = "take the parameter by value; a slice `&[T]` of anything but bytes \
needs the thruput-sdk `alloc` feature; a type of your own becomes \
usable by reference with `#[contract_type]` or a \
`thruput_sdk::call::OwnedRefArg` impl"
)]
pub trait RefArg<'r> {
type Decoded: ReadXDR<'r> + ReceiveAuthHandles;
fn get(decoded: &Self::Decoded) -> &Self;
}
pub trait OwnedRefArg {}
impl<'r, T> RefArg<'r> for T
where
T: OwnedRefArg + ReadXDR<'r> + ReceiveAuthHandles,
{
type Decoded = T;
#[inline(always)]
fn get(decoded: &Self::Decoded) -> &Self {
decoded
}
}
pub trait RefArgElement {}
impl<T: OwnedRefArg> RefArgElement for T {}
macro_rules! borrowed_ref_arg {
($($ty:ty),* $(,)?) => {$(
impl<'r> RefArg<'r> for $ty {
type Decoded = &'r $ty;
#[inline(always)]
fn get(decoded: &Self::Decoded) -> &Self {
decoded
}
}
)*};
}
borrowed_ref_arg!([u8], str);
macro_rules! borrowed_sized_ref_arg {
($($ty:ty),* $(,)?) => {$(
borrowed_ref_arg!($ty);
impl RefArgElement for $ty {}
)*};
}
borrowed_sized_ref_arg!(
crate::types::ContractAddress,
crate::types::ContractEntrypointID,
crate::types::Ed25519PublicKey,
crate::types::Ed25519Signature,
crate::types::MlDsa65PublicKey,
crate::types::MlDsa65Signature,
crate::types::SHA256Hash,
);
impl OwnedRefArg for crate::types::PublicKey {}
impl OwnedRefArg for crate::types::Signature {}
impl<'r, const N: usize> RefArg<'r> for [u8; N] {
type Decoded = &'r [u8; N];
#[inline(always)]
fn get(decoded: &Self::Decoded) -> &Self {
decoded
}
}
impl<const N: usize> RefArgElement for [u8; N] {}
impl RefArgElement for &[u8] {}
impl RefArgElement for &str {}
#[cfg(feature = "alloc")]
impl<'r, T> RefArg<'r> for [T]
where
T: RefArgElement + ReadXDR<'r> + ReceiveAuthHandles,
{
type Decoded = alloc::vec::Vec<T>;
#[inline(always)]
fn get(decoded: &Self::Decoded) -> &Self {
decoded
}
}
macro_rules! owned_ref_arg {
($($ty:ty),* $(,)?) => {$(
impl OwnedRefArg for $ty {}
)*};
}
owned_ref_arg!(
u16,
u32,
u64,
u128,
i8,
i16,
i32,
i64,
i128,
bool,
(),
crate::types::BlockHeight,
thruput_u256::U256,
thruput_u256::I256,
);
impl<T> OwnedRefArg for Option<T> {}
impl<T: RefArgElement, const N: usize> OwnedRefArg for [T; N] {}
impl<T, const N: usize> OwnedRefArg for heapless::Vec<T, N> {}
impl<const N: usize> OwnedRefArg for heapless::String<N> {}
impl<const MAX: u32> OwnedRefArg for xdrs::BytesM<MAX> {}
impl<T> OwnedRefArg for crate::signer::Signed<T> {}
#[cfg(feature = "alloc")]
impl<T, const MAX: u32> OwnedRefArg for xdrs::VecM<T, MAX> {}
#[cfg(feature = "alloc")]
impl<T> OwnedRefArg for alloc::vec::Vec<T> {}
#[cfg(feature = "alloc")]
impl<T: ?Sized> OwnedRefArg for alloc::boxed::Box<T> {}
macro_rules! owned_ref_arg_tuple {
($(($($name:ident),+)),* $(,)?) => {$(
impl<$($name),+> OwnedRefArg for ($($name,)+) {}
)*};
}
owned_ref_arg_tuple!(
(A),
(A, B),
(A, B, C),
(A, B, C, D),
(A, B, C, D, E),
(A, B, C, D, E, F),
(A, B, C, D, E, F, G),
(A, B, C, D, E, F, G, H),
(A, B, C, D, E, F, G, H, I),
(A, B, C, D, E, F, G, H, I, J),
(A, B, C, D, E, F, G, H, I, J, K),
(A, B, C, D, E, F, G, H, I, J, K, L),
(A, B, C, D, E, F, G, H, I, J, K, L, M),
(A, B, C, D, E, F, G, H, I, J, K, L, M, N),
(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O),
(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P),
);