use crate::FaultString;
#[cfg(not(feature = "alloc"))]
const AUTH_HANDLES_MAX: usize = 64;
#[cfg(not(feature = "alloc"))]
pub type AuthHandleBuf = heapless::Vec<u32, AUTH_HANDLES_MAX>;
#[cfg(feature = "alloc")]
pub type AuthHandleBuf = alloc::vec::Vec<u32>;
pub trait CollectAuthHandles {
fn collect_auth_handles(
&self,
out: &mut AuthHandleBuf,
) -> Result<(), FaultString>;
}
macro_rules! impl_collect_noop {
($($ty:ty),+ $(,)?) => {
$(
impl CollectAuthHandles for $ty {
#[inline(always)]
fn collect_auth_handles(&self, _out: &mut AuthHandleBuf) -> Result<(), FaultString> {
Ok(())
}
}
)+
};
}
impl_collect_noop!(
u8,
u16,
u32,
u64,
u128,
i8,
i16,
i32,
i64,
i128,
bool,
(),
str,
crate::types::ContractAddress,
crate::types::BlockHeight,
crate::types::SHA256Hash,
crate::types::Ed25519PublicKey,
crate::types::Ed25519Signature,
crate::types::MlDsa65PublicKey,
crate::types::MlDsa65Signature,
crate::types::PublicKey,
crate::types::Signature,
thruput_u256::U256,
thruput_u256::I256,
crate::types::ContractEntrypointID,
);
#[cfg(feature = "alloc")]
impl_collect_noop!(alloc::string::String);
impl<T: CollectAuthHandles, const N: usize> CollectAuthHandles for [T; N] {
#[inline(always)]
fn collect_auth_handles(
&self,
out: &mut AuthHandleBuf,
) -> Result<(), FaultString> {
for item in self {
item.collect_auth_handles(out)?;
}
Ok(())
}
}
impl<T: CollectAuthHandles + ?Sized> CollectAuthHandles for &T {
#[inline(always)]
fn collect_auth_handles(
&self,
out: &mut AuthHandleBuf,
) -> Result<(), FaultString> {
(**self).collect_auth_handles(out)
}
}
impl<T: CollectAuthHandles> CollectAuthHandles for Option<T> {
#[inline(always)]
fn collect_auth_handles(
&self,
out: &mut AuthHandleBuf,
) -> Result<(), FaultString> {
if let Some(inner) = self {
inner.collect_auth_handles(out)?;
}
Ok(())
}
}
impl<T: CollectAuthHandles> CollectAuthHandles for [T] {
#[inline(always)]
fn collect_auth_handles(
&self,
out: &mut AuthHandleBuf,
) -> Result<(), FaultString> {
for item in self {
item.collect_auth_handles(out)?;
}
Ok(())
}
}
#[cfg(feature = "alloc")]
impl<T: CollectAuthHandles, const MAX: u32> CollectAuthHandles
for xdrs::VecM<T, MAX>
{
#[inline(always)]
fn collect_auth_handles(
&self,
out: &mut AuthHandleBuf,
) -> Result<(), FaultString> {
self.0.as_slice().collect_auth_handles(out)
}
}
impl<const MAX: u32> CollectAuthHandles for xdrs::BytesM<MAX> {
#[inline(always)]
fn collect_auth_handles(
&self,
_out: &mut AuthHandleBuf,
) -> Result<(), FaultString> {
Ok(())
}
}
impl<const MAX: usize, T: CollectAuthHandles> CollectAuthHandles
for heapless::Vec<T, MAX>
{
#[inline(always)]
fn collect_auth_handles(
&self,
out: &mut AuthHandleBuf,
) -> Result<(), FaultString> {
for item in self {
item.collect_auth_handles(out)?;
}
Ok(())
}
}
impl<const MAX: usize> CollectAuthHandles for heapless::String<MAX> {
#[inline(always)]
fn collect_auth_handles(
&self,
_out: &mut AuthHandleBuf,
) -> Result<(), FaultString> {
Ok(())
}
}
#[cfg(feature = "alloc")]
impl<T: CollectAuthHandles + ?Sized> CollectAuthHandles
for alloc::boxed::Box<T>
{
#[inline(always)]
fn collect_auth_handles(
&self,
out: &mut AuthHandleBuf,
) -> Result<(), FaultString> {
(**self).collect_auth_handles(out)
}
}
#[cfg(feature = "alloc")]
impl<T: CollectAuthHandles> CollectAuthHandles for alloc::vec::Vec<T> {
#[inline(always)]
fn collect_auth_handles(
&self,
out: &mut AuthHandleBuf,
) -> Result<(), FaultString> {
self.as_slice().collect_auth_handles(out)
}
}
macro_rules! impl_collect_tuple {
($(($($name:ident),+)),+ $(,)?) => {
$(
impl<$($name: CollectAuthHandles),+> CollectAuthHandles for ($($name,)+) {
#[inline(always)]
#[allow(non_snake_case)]
fn collect_auth_handles(&self, out: &mut AuthHandleBuf) -> Result<(), FaultString> {
let ($($name,)+) = self;
$($name.collect_auth_handles(out)?;)+
Ok(())
}
}
)+
};
}
impl_collect_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),
(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q),
(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R),
(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S),
(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T),
);
#[cfg(test)]
mod tests {
use super::*;
use crate::signer::Signed;
#[test]
fn primitives_collect_nothing() {
let mut buf = AuthHandleBuf::new();
42u64.collect_auth_handles(&mut buf).unwrap();
true.collect_auth_handles(&mut buf).unwrap();
(-1i32).collect_auth_handles(&mut buf).unwrap();
assert!(buf.is_empty());
}
#[test]
fn signer_collects_handle() {
let mut buf = AuthHandleBuf::new();
let s: Signed<u32> = Signed::from_handle(99);
s.collect_auth_handles(&mut buf).unwrap();
assert_eq!(buf.as_slice(), &[99]);
}
#[test]
fn option_some_collects() {
let mut buf = AuthHandleBuf::new();
let s: Option<Signed<u32>> = Some(Signed::from_handle(5));
s.collect_auth_handles(&mut buf).unwrap();
assert_eq!(buf.as_slice(), &[5]);
}
#[test]
fn option_none_collects_nothing() {
let mut buf = AuthHandleBuf::new();
let s: Option<Signed<u32>> = None;
s.collect_auth_handles(&mut buf).unwrap();
assert!(buf.is_empty());
}
#[test]
fn slice_of_signeds() {
let mut buf = AuthHandleBuf::new();
let signeds: &[Signed<u32>] = &[
Signed::from_handle(1),
Signed::from_handle(2),
Signed::from_handle(3),
];
signeds.collect_auth_handles(&mut buf).unwrap();
assert_eq!(buf.as_slice(), &[1, 2, 3]);
}
#[test]
fn mixed_tuple_collects_only_signeds() {
let mut buf = AuthHandleBuf::new();
let args: (u64, Signed<u32>, i32, Signed<bool>) =
(100, Signed::from_handle(10), -1, Signed::from_handle(20));
args.collect_auth_handles(&mut buf).unwrap();
assert_eq!(buf.as_slice(), &[10, 20]);
}
#[test]
fn single_element_tuple() {
let mut buf = AuthHandleBuf::new();
let args: (Signed<u32>,) = (Signed::from_handle(42),);
args.collect_auth_handles(&mut buf).unwrap();
assert_eq!(buf.as_slice(), &[42]);
}
#[test]
fn tuple_with_no_signeds() {
let mut buf = AuthHandleBuf::new();
let args: (u64, i32, bool) = (1, 2, true);
args.collect_auth_handles(&mut buf).unwrap();
assert!(buf.is_empty());
}
}