1use crate::FaultString;
2
3#[cfg(not(feature = "alloc"))]
4const AUTH_HANDLES_MAX: usize = 64;
5#[cfg(not(feature = "alloc"))]
6pub type AuthHandleBuf = heapless::Vec<u32, AUTH_HANDLES_MAX>;
7#[cfg(feature = "alloc")]
8pub type AuthHandleBuf = alloc::vec::Vec<u32>;
9
10pub trait CollectAuthHandles {
23 fn collect_auth_handles(
24 &self,
25 out: &mut AuthHandleBuf,
26 ) -> Result<(), FaultString>;
27}
28
29macro_rules! impl_collect_noop {
30 ($($ty:ty),+ $(,)?) => {
31 $(
32 impl CollectAuthHandles for $ty {
33 #[inline(always)]
34 fn collect_auth_handles(&self, _out: &mut AuthHandleBuf) -> Result<(), FaultString> {
35 Ok(())
36 }
37 }
38 )+
39 };
40}
41
42impl_collect_noop!(
43 u8,
44 u16,
45 u32,
46 u64,
47 u128,
48 i8,
49 i16,
50 i32,
51 i64,
52 i128,
53 bool,
54 (),
55 str,
56 crate::types::ContractAddress,
57 crate::types::BlockHeight,
58 crate::types::SHA256Hash,
59 crate::types::Ed25519PublicKey,
60 crate::types::Ed25519Signature,
61 crate::types::MlDsa65PublicKey,
62 crate::types::MlDsa65Signature,
63 crate::types::PublicKey,
64 crate::types::Signature,
65 thruput_u256::U256,
66 thruput_u256::I256,
67 crate::types::ContractEntrypointID,
68);
69
70#[cfg(feature = "alloc")]
71impl_collect_noop!(alloc::string::String);
72
73impl<T: CollectAuthHandles, const N: usize> CollectAuthHandles for [T; N] {
74 #[inline(always)]
75 fn collect_auth_handles(
76 &self,
77 out: &mut AuthHandleBuf,
78 ) -> Result<(), FaultString> {
79 for item in self {
80 item.collect_auth_handles(out)?;
81 }
82 Ok(())
83 }
84}
85
86impl<T: CollectAuthHandles + ?Sized> CollectAuthHandles for &T {
87 #[inline(always)]
88 fn collect_auth_handles(
89 &self,
90 out: &mut AuthHandleBuf,
91 ) -> Result<(), FaultString> {
92 (**self).collect_auth_handles(out)
93 }
94}
95
96impl<T: CollectAuthHandles> CollectAuthHandles for Option<T> {
97 #[inline(always)]
98 fn collect_auth_handles(
99 &self,
100 out: &mut AuthHandleBuf,
101 ) -> Result<(), FaultString> {
102 if let Some(inner) = self {
103 inner.collect_auth_handles(out)?;
104 }
105 Ok(())
106 }
107}
108
109impl<T: CollectAuthHandles> CollectAuthHandles for [T] {
110 #[inline(always)]
111 fn collect_auth_handles(
112 &self,
113 out: &mut AuthHandleBuf,
114 ) -> Result<(), FaultString> {
115 for item in self {
116 item.collect_auth_handles(out)?;
117 }
118 Ok(())
119 }
120}
121
122#[cfg(feature = "alloc")]
123impl<T: CollectAuthHandles, const MAX: u32> CollectAuthHandles
124 for xdrs::VecM<T, MAX>
125{
126 #[inline(always)]
127 fn collect_auth_handles(
128 &self,
129 out: &mut AuthHandleBuf,
130 ) -> Result<(), FaultString> {
131 self.0.as_slice().collect_auth_handles(out)
132 }
133}
134
135impl<const MAX: u32> CollectAuthHandles for xdrs::BytesM<MAX> {
136 #[inline(always)]
137 fn collect_auth_handles(
138 &self,
139 _out: &mut AuthHandleBuf,
140 ) -> Result<(), FaultString> {
141 Ok(())
142 }
143}
144
145impl<const MAX: usize, T: CollectAuthHandles> CollectAuthHandles
146 for heapless::Vec<T, MAX>
147{
148 #[inline(always)]
149 fn collect_auth_handles(
150 &self,
151 out: &mut AuthHandleBuf,
152 ) -> Result<(), FaultString> {
153 for item in self {
154 item.collect_auth_handles(out)?;
155 }
156 Ok(())
157 }
158}
159
160impl<const MAX: usize> CollectAuthHandles for heapless::String<MAX> {
161 #[inline(always)]
162 fn collect_auth_handles(
163 &self,
164 _out: &mut AuthHandleBuf,
165 ) -> Result<(), FaultString> {
166 Ok(())
167 }
168}
169
170#[cfg(feature = "alloc")]
171impl<T: CollectAuthHandles + ?Sized> CollectAuthHandles
172 for alloc::boxed::Box<T>
173{
174 #[inline(always)]
175 fn collect_auth_handles(
176 &self,
177 out: &mut AuthHandleBuf,
178 ) -> Result<(), FaultString> {
179 (**self).collect_auth_handles(out)
180 }
181}
182
183#[cfg(feature = "alloc")]
184impl<T: CollectAuthHandles> CollectAuthHandles for alloc::vec::Vec<T> {
185 #[inline(always)]
186 fn collect_auth_handles(
187 &self,
188 out: &mut AuthHandleBuf,
189 ) -> Result<(), FaultString> {
190 self.as_slice().collect_auth_handles(out)
191 }
192}
193
194macro_rules! impl_collect_tuple {
195 ($(($($name:ident),+)),+ $(,)?) => {
196 $(
197 impl<$($name: CollectAuthHandles),+> CollectAuthHandles for ($($name,)+) {
198 #[inline(always)]
199 #[allow(non_snake_case)]
200 fn collect_auth_handles(&self, out: &mut AuthHandleBuf) -> Result<(), FaultString> {
201 let ($($name,)+) = self;
202 $($name.collect_auth_handles(out)?;)+
203 Ok(())
204 }
205 }
206 )+
207 };
208}
209
210impl_collect_tuple!(
211 (A),
212 (A, B),
213 (A, B, C),
214 (A, B, C, D),
215 (A, B, C, D, E),
216 (A, B, C, D, E, F),
217 (A, B, C, D, E, F, G),
218 (A, B, C, D, E, F, G, H),
219 (A, B, C, D, E, F, G, H, I),
220 (A, B, C, D, E, F, G, H, I, J),
221 (A, B, C, D, E, F, G, H, I, J, K),
222 (A, B, C, D, E, F, G, H, I, J, K, L),
223 (A, B, C, D, E, F, G, H, I, J, K, L, M),
224 (A, B, C, D, E, F, G, H, I, J, K, L, M, N),
225 (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O),
226 (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P),
227 (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q),
228 (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R),
229 (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S),
230 (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T),
231);
232
233#[cfg(test)]
234mod tests {
235 use super::*;
236 use crate::signer::Signed;
237
238 #[test]
239 fn primitives_collect_nothing() {
240 let mut buf = AuthHandleBuf::new();
241 42u64.collect_auth_handles(&mut buf).unwrap();
242 true.collect_auth_handles(&mut buf).unwrap();
243 (-1i32).collect_auth_handles(&mut buf).unwrap();
244 assert!(buf.is_empty());
245 }
246
247 #[test]
248 fn signer_collects_handle() {
249 let mut buf = AuthHandleBuf::new();
250 let s: Signed<u32> = Signed::from_handle(99);
251 s.collect_auth_handles(&mut buf).unwrap();
252 assert_eq!(buf.as_slice(), &[99]);
253 }
254
255 #[test]
256 fn option_some_collects() {
257 let mut buf = AuthHandleBuf::new();
258 let s: Option<Signed<u32>> = Some(Signed::from_handle(5));
259 s.collect_auth_handles(&mut buf).unwrap();
260 assert_eq!(buf.as_slice(), &[5]);
261 }
262
263 #[test]
264 fn option_none_collects_nothing() {
265 let mut buf = AuthHandleBuf::new();
266 let s: Option<Signed<u32>> = None;
267 s.collect_auth_handles(&mut buf).unwrap();
268 assert!(buf.is_empty());
269 }
270
271 #[test]
272 fn slice_of_signeds() {
273 let mut buf = AuthHandleBuf::new();
274 let signeds: &[Signed<u32>] = &[
275 Signed::from_handle(1),
276 Signed::from_handle(2),
277 Signed::from_handle(3),
278 ];
279 signeds.collect_auth_handles(&mut buf).unwrap();
280 assert_eq!(buf.as_slice(), &[1, 2, 3]);
281 }
282
283 #[test]
284 fn mixed_tuple_collects_only_signeds() {
285 let mut buf = AuthHandleBuf::new();
286 let args: (u64, Signed<u32>, i32, Signed<bool>) =
287 (100, Signed::from_handle(10), -1, Signed::from_handle(20));
288 args.collect_auth_handles(&mut buf).unwrap();
289 assert_eq!(buf.as_slice(), &[10, 20]);
290 }
291
292 #[test]
293 fn single_element_tuple() {
294 let mut buf = AuthHandleBuf::new();
295 let args: (Signed<u32>,) = (Signed::from_handle(42),);
296 args.collect_auth_handles(&mut buf).unwrap();
297 assert_eq!(buf.as_slice(), &[42]);
298 }
299
300 #[test]
301 fn tuple_with_no_signeds() {
302 let mut buf = AuthHandleBuf::new();
303 let args: (u64, i32, bool) = (1, 2, true);
304 args.collect_auth_handles(&mut buf).unwrap();
305 assert!(buf.is_empty());
306 }
307}