1use crate::{AuthTokenError, FaultString};
2
3pub fn receive_auth_handles_from_iter<T: ReceiveAuthHandles>(
4 value: &mut T,
5 handles: impl IntoIterator<Item = u32>,
6) -> Result<(), AuthTokenError> {
7 let mut iter = handles.into_iter();
8 value.receive_auth_handles(&mut iter)?;
9
10 if iter.next().is_some() {
11 Err(AuthTokenError::ReceiveAuthHandlesFailure(
12 FaultString::from_display("unexpected auth handle remaining"),
13 ))
14 } else {
15 Ok(())
16 }
17}
18
19pub trait ReceiveAuthHandles {
37 fn receive_auth_handles(
38 &mut self,
39 handles: &mut impl Iterator<Item = u32>,
40 ) -> Result<(), AuthTokenError>;
41}
42
43macro_rules! impl_receive_noop {
44 ($($ty:ty),+ $(,)?) => {
45 $(
46 impl ReceiveAuthHandles for $ty {
47 #[inline(always)]
48 fn receive_auth_handles(&mut self, _handles: &mut impl Iterator<Item = u32>) -> Result<(), AuthTokenError> {
49 Ok(())
50 }
51 }
52 )+
53 };
54}
55
56impl_receive_noop!(
57 u8,
58 u16,
59 u32,
60 u64,
61 u128,
62 i8,
63 i16,
64 i32,
65 i64,
66 i128,
67 bool,
68 (),
69 str,
70 crate::types::ContractAddress,
71 crate::types::BlockHeight,
72 crate::types::SHA256Hash,
73 crate::types::Ed25519PublicKey,
74 crate::types::Ed25519Signature,
75 crate::types::MlDsa65PublicKey,
76 crate::types::MlDsa65Signature,
77 crate::types::PublicKey,
78 crate::types::Signature,
79 thruput_u256::U256,
80 thruput_u256::I256,
81 crate::types::ContractEntrypointID,
82);
83
84#[cfg(feature = "alloc")]
85impl_receive_noop!(alloc::string::String);
86
87impl<T: ReceiveAuthHandles, const N: usize> ReceiveAuthHandles for [T; N] {
88 #[inline(always)]
89 fn receive_auth_handles(
90 &mut self,
91 handles: &mut impl Iterator<Item = u32>,
92 ) -> Result<(), AuthTokenError> {
93 for item in self {
94 item.receive_auth_handles(handles)?;
95 }
96 Ok(())
97 }
98}
99
100impl<T: ReceiveAuthHandles + ?Sized> ReceiveAuthHandles for &mut T {
101 #[inline(always)]
102 fn receive_auth_handles(
103 &mut self,
104 handles: &mut impl Iterator<Item = u32>,
105 ) -> Result<(), AuthTokenError> {
106 (**self).receive_auth_handles(handles)
107 }
108}
109
110impl<T: ReceiveAuthHandles> ReceiveAuthHandles for Option<T> {
111 #[inline(always)]
112 fn receive_auth_handles(
113 &mut self,
114 handles: &mut impl Iterator<Item = u32>,
115 ) -> Result<(), AuthTokenError> {
116 if let Some(inner) = self {
117 return inner.receive_auth_handles(handles);
118 }
119 Ok(())
120 }
121}
122
123impl<T: ReceiveAuthHandles> ReceiveAuthHandles for [T] {
124 #[inline(always)]
125 fn receive_auth_handles(
126 &mut self,
127 handles: &mut impl Iterator<Item = u32>,
128 ) -> Result<(), AuthTokenError> {
129 for item in self {
130 item.receive_auth_handles(handles)?;
131 }
132 Ok(())
133 }
134}
135
136#[cfg(feature = "alloc")]
137impl<T: ReceiveAuthHandles, const MAX: u32> ReceiveAuthHandles
138 for xdrs::VecM<T, MAX>
139{
140 #[inline(always)]
141 fn receive_auth_handles(
142 &mut self,
143 handles: &mut impl Iterator<Item = u32>,
144 ) -> Result<(), AuthTokenError> {
145 for item in self.0.iter_mut() {
146 item.receive_auth_handles(handles)?;
147 }
148 Ok(())
149 }
150}
151
152impl<const MAX: u32> ReceiveAuthHandles for xdrs::BytesM<MAX> {
153 #[inline(always)]
154 fn receive_auth_handles(
155 &mut self,
156 _handles: &mut impl Iterator<Item = u32>,
157 ) -> Result<(), AuthTokenError> {
158 Ok(())
159 }
160}
161
162impl<const MAX: usize, T: ReceiveAuthHandles> ReceiveAuthHandles
163 for heapless::Vec<T, MAX>
164{
165 #[inline(always)]
166 fn receive_auth_handles(
167 &mut self,
168 handles: &mut impl Iterator<Item = u32>,
169 ) -> Result<(), AuthTokenError> {
170 for item in self {
171 item.receive_auth_handles(handles)?;
172 }
173 Ok(())
174 }
175}
176
177impl<const MAX: usize> ReceiveAuthHandles for heapless::String<MAX> {
178 #[inline(always)]
179 fn receive_auth_handles(
180 &mut self,
181 _handles: &mut impl Iterator<Item = u32>,
182 ) -> Result<(), AuthTokenError> {
183 Ok(())
184 }
185}
186
187#[cfg(feature = "alloc")]
188impl<T: ReceiveAuthHandles + ?Sized> ReceiveAuthHandles
189 for alloc::boxed::Box<T>
190{
191 #[inline(always)]
192 fn receive_auth_handles(
193 &mut self,
194 handles: &mut impl Iterator<Item = u32>,
195 ) -> Result<(), AuthTokenError> {
196 (**self).receive_auth_handles(handles)
197 }
198}
199
200impl<T: ReceiveAuthHandles + ?Sized> ReceiveAuthHandles for &T {
201 #[inline(always)]
202 fn receive_auth_handles(
203 &mut self,
204 _handles: &mut impl Iterator<Item = u32>,
205 ) -> Result<(), AuthTokenError> {
206 Ok(())
207 }
208}
209
210#[cfg(feature = "alloc")]
211impl<T: ReceiveAuthHandles> ReceiveAuthHandles for alloc::vec::Vec<T> {
212 #[inline(always)]
213 fn receive_auth_handles(
214 &mut self,
215 handles: &mut impl Iterator<Item = u32>,
216 ) -> Result<(), AuthTokenError> {
217 self.as_mut_slice().receive_auth_handles(handles)
218 }
219}
220
221macro_rules! impl_receive_tuple {
222 ($(($($name:ident),+)),+ $(,)?) => {
223 $(
224 impl<$($name: ReceiveAuthHandles),+> ReceiveAuthHandles for ($($name,)+) {
225 #[inline(always)]
226 #[allow(non_snake_case)]
227 fn receive_auth_handles(&mut self, handles: &mut impl Iterator<Item = u32>) -> Result<(), AuthTokenError> {
228 let ($($name,)+) = self;
229 $($name.receive_auth_handles(handles)?;)+
230 Ok(())
231 }
232 }
233 )+
234 };
235}
236
237impl_receive_tuple!(
238 (A),
239 (A, B),
240 (A, B, C),
241 (A, B, C, D),
242 (A, B, C, D, E),
243 (A, B, C, D, E, F),
244 (A, B, C, D, E, F, G),
245 (A, B, C, D, E, F, G, H),
246 (A, B, C, D, E, F, G, H, I),
247 (A, B, C, D, E, F, G, H, I, J),
248 (A, B, C, D, E, F, G, H, I, J, K),
249 (A, B, C, D, E, F, G, H, I, J, K, L),
250 (A, B, C, D, E, F, G, H, I, J, K, L, M),
251 (A, B, C, D, E, F, G, H, I, J, K, L, M, N),
252 (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O),
253 (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P),
254 (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q),
255 (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R),
256 (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S),
257 (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T),
258);
259
260#[cfg(test)]
261mod tests {
262 use super::*;
263 use crate::signer::Signed;
264
265 #[test]
266 fn primitives_receive_nothing() {
267 let mut x = 42u64;
268 let mut handles = core::iter::empty();
269 x.receive_auth_handles(&mut handles).unwrap();
270 }
271
272 #[test]
273 fn signer_receives_handle() {
274 let mut s: Signed<u32> = Signed::from_handle(u32::MAX);
275 let mut iter = [99u32].into_iter();
276 s.receive_auth_handles(&mut iter).unwrap();
277 assert_eq!(s.handle(), 99);
278 }
279
280 #[test]
281 fn option_some_receives() {
282 let mut s: Option<Signed<u32>> = Some(Signed::from_handle(u32::MAX));
283 let mut iter = [5u32].into_iter();
284 s.receive_auth_handles(&mut iter).unwrap();
285 assert_eq!(s.unwrap().handle(), 5);
286 }
287
288 #[test]
289 fn option_none_skips() {
290 let mut s: Option<Signed<u32>> = None;
291 let mut iter = [5u32].into_iter();
292 s.receive_auth_handles(&mut iter).unwrap();
293 assert_eq!(iter.next(), Some(5));
295 }
296
297 #[test]
298 fn mixed_tuple_receives_in_order() {
299 let mut args: (u64, Signed<u32>, i32, Signed<bool>) = (
300 100,
301 Signed::from_handle(u32::MAX),
302 -1,
303 Signed::from_handle(u32::MAX),
304 );
305 let mut iter = [10u32, 20u32].into_iter();
306 args.receive_auth_handles(&mut iter).unwrap();
307 assert_eq!(args.1.handle(), 10);
308 assert_eq!(args.3.handle(), 20);
309 }
310
311 #[cfg(feature = "alloc")]
312 #[test]
313 fn owned_strings_preserve_signed_handle_order() {
314 use crate::{AuthHandleBuf, CollectAuthHandles};
315
316 let mut args = (
317 alloc::string::String::from("before 🦀"),
318 Signed::<u32>::from_handle(7),
319 Some(alloc::string::String::from("between")),
320 Signed::<bool>::from_handle(9),
321 );
322 let mut collected = AuthHandleBuf::new();
323 args.collect_auth_handles(&mut collected).unwrap();
324 assert_eq!(collected.as_slice(), &[7, 9]);
325
326 let mut received = [11, 13].into_iter();
327 args.receive_auth_handles(&mut received).unwrap();
328 assert_eq!(args.0, "before 🦀");
329 assert_eq!(args.1.handle(), 11);
330 assert_eq!(args.2.as_deref(), Some("between"));
331 assert_eq!(args.3.handle(), 13);
332 assert_eq!(received.next(), None);
333 }
334
335 #[test]
336 fn array_receives_handles_in_order() {
337 let mut arr: [Signed<u32>; 2] =
338 [Signed::from_handle(u32::MAX), Signed::from_handle(u32::MAX)];
339 let mut iter = [7u32, 8u32].into_iter();
340 arr.receive_auth_handles(&mut iter).unwrap();
341 assert_eq!(arr[0].handle(), 7);
342 assert_eq!(arr[1].handle(), 8);
343 assert_eq!(iter.next(), None);
344 }
345
346 #[test]
347 fn struct_field_after_array_gets_correct_handle() {
348 let mut args: ([Signed<u32>; 2], Signed<bool>) = (
351 [Signed::from_handle(u32::MAX), Signed::from_handle(u32::MAX)],
352 Signed::from_handle(u32::MAX),
353 );
354 let mut iter = [1u32, 2u32, 3u32].into_iter();
355 args.receive_auth_handles(&mut iter).unwrap();
356 assert_eq!(args.0[0].handle(), 1);
357 assert_eq!(args.0[1].handle(), 2);
358 assert_eq!(args.1.handle(), 3);
359 }
360
361 #[test]
362 fn receive_insufficient_handles() {
363 let mut args: (u64, Signed<u32>, i32, Signed<bool>) = (
364 100,
365 Signed::from_handle(u32::MAX),
366 -1,
367 Signed::from_handle(u32::MAX),
368 );
369 let mut iter = [10u32].into_iter();
370 args.receive_auth_handles(&mut iter).unwrap_err();
371 }
372}