1use crate::encode::{EncodeArgument, EncodeArguments, EncodeReturn};
2use crate::rc::{Allocated, Retained};
3use crate::runtime::{AnyObject, Bool, Sel};
4use crate::Message;
5
6mod argument_private {
7 pub trait Sealed {}
8}
9
10pub trait ConvertArgument: argument_private::Sealed {
19 #[doc(hidden)]
21 type __Inner: EncodeArgument;
22
23 #[doc(hidden)]
28 type __WritebackOnDrop: Sized;
29
30 #[doc(hidden)]
31 fn __from_defined_param(inner: Self::__Inner) -> Self;
32
33 #[doc(hidden)]
43 unsafe fn __into_argument(self) -> (Self::__Inner, Self::__WritebackOnDrop);
44}
45
46impl<T: Message> argument_private::Sealed for &mut Retained<T> {}
48impl<T: Message> argument_private::Sealed for Option<&mut Retained<T>> {}
49impl<T: Message> argument_private::Sealed for &mut Option<Retained<T>> {}
50impl<T: Message> argument_private::Sealed for Option<&mut Option<Retained<T>>> {}
51
52impl<T: EncodeArgument> argument_private::Sealed for T {}
53impl<T: EncodeArgument> ConvertArgument for T {
54 type __Inner = Self;
55
56 type __WritebackOnDrop = ();
57
58 #[inline]
59 fn __from_defined_param(inner: Self::__Inner) -> Self {
60 inner
61 }
62
63 #[inline]
64 unsafe fn __into_argument(self) -> (Self::__Inner, Self::__WritebackOnDrop) {
65 (self, ())
66 }
67}
68
69impl argument_private::Sealed for bool {}
70impl ConvertArgument for bool {
71 type __Inner = Bool;
72
73 type __WritebackOnDrop = ();
74
75 #[inline]
76 fn __from_defined_param(inner: Self::__Inner) -> Self {
77 inner.as_bool()
78 }
79
80 #[inline]
81 unsafe fn __into_argument(self) -> (Self::__Inner, Self::__WritebackOnDrop) {
82 (Bool::new(self), ())
83 }
84}
85
86mod return_private {
87 pub trait Sealed {}
88}
89
90pub trait ConvertReturn<MethodFamily>: return_private::Sealed {
94 type Inner: EncodeReturn;
95
96 #[track_caller]
97 unsafe fn convert_message_return(
98 inner: Self::Inner,
99 receiver_ptr: *mut AnyObject,
100 sel: Sel,
101 ) -> Self;
102
103 fn convert_defined_return(self) -> Self::Inner;
104}
105
106impl<T: EncodeReturn> return_private::Sealed for T {}
107impl<T: EncodeReturn, MethodFamily> ConvertReturn<MethodFamily> for T {
108 type Inner = Self;
109
110 #[inline]
111 unsafe fn convert_message_return(
112 inner: Self::Inner,
113 _receiver_ptr: *mut AnyObject,
114 _sel: Sel,
115 ) -> Self {
116 inner
117 }
118
119 #[inline]
120 fn convert_defined_return(self) -> Self::Inner {
121 self
122 }
123}
124
125impl return_private::Sealed for bool {}
126impl<MethodFamily> ConvertReturn<MethodFamily> for bool {
127 type Inner = Bool;
128
129 #[inline]
130 unsafe fn convert_message_return(
131 inner: Self::Inner,
132 _receiver_ptr: *mut AnyObject,
133 _sel: Sel,
134 ) -> Self {
135 inner.as_bool()
136 }
137
138 #[inline]
139 fn convert_defined_return(self) -> Self::Inner {
140 Bool::new(self)
141 }
142}
143
144impl<T: ?Sized + Message> return_private::Sealed for Retained<T> {}
146impl<T: ?Sized + Message> return_private::Sealed for Option<Retained<T>> {}
147impl<T: ?Sized + Message> return_private::Sealed for Allocated<T> {}
148
149pub trait ConvertArguments {
150 #[doc(hidden)]
151 type __Inner: EncodeArguments;
152
153 #[doc(hidden)]
154 type __WritebackOnDrop: Sized;
155
156 #[doc(hidden)]
157 unsafe fn __into_arguments(self) -> (Self::__Inner, Self::__WritebackOnDrop);
158}
159
160pub trait TupleExtender<T> {
161 #[doc(hidden)]
162 type PlusOneArgument;
163 #[doc(hidden)]
164 fn add_argument(self, arg: T) -> Self::PlusOneArgument;
165}
166
167macro_rules! args_impl {
168 ($($a:ident: $t:ident),*) => (
169 impl<$($t: ConvertArgument),*> ConvertArguments for ($($t,)*) {
170 type __Inner = ($($t::__Inner,)*);
171
172 type __WritebackOnDrop = ($($t::__WritebackOnDrop,)*);
173
174 #[inline]
175 unsafe fn __into_arguments(self) -> (Self::__Inner, Self::__WritebackOnDrop) {
176 let ($($a,)*) = self;
177 $(let $a = unsafe { ConvertArgument::__into_argument($a) };)*
179
180 (($($a.0,)*), ($($a.1,)*))
181 }
182 }
183
184 impl<$($t,)* T> TupleExtender<T> for ($($t,)*) {
185 type PlusOneArgument = ($($t,)* T,);
186
187 #[inline]
188 fn add_argument(self, arg: T) -> Self::PlusOneArgument {
189 let ($($a,)*) = self;
190 ($($a,)* arg,)
191 }
192 }
193 );
194}
195
196args_impl!();
197args_impl!(a: A);
198args_impl!(a: A, b: B);
199args_impl!(a: A, b: B, c: C);
200args_impl!(a: A, b: B, c: C, d: D);
201args_impl!(a: A, b: B, c: C, d: D, e: E);
202args_impl!(a: A, b: B, c: C, d: D, e: E, f: F);
203args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G);
204args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H);
205args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I);
206args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J);
207args_impl!(
208 a: A,
209 b: B,
210 c: C,
211 d: D,
212 e: E,
213 f: F,
214 g: G,
215 h: H,
216 i: I,
217 j: J,
218 k: K
219);
220args_impl!(
221 a: A,
222 b: B,
223 c: C,
224 d: D,
225 e: E,
226 f: F,
227 g: G,
228 h: H,
229 i: I,
230 j: J,
231 k: K,
232 l: L
233);
234args_impl!(
235 a: A,
236 b: B,
237 c: C,
238 d: D,
239 e: E,
240 f: F,
241 g: G,
242 h: H,
243 i: I,
244 j: J,
245 k: K,
246 l: L,
247 m: M
248);
249args_impl!(
250 a: A,
251 b: B,
252 c: C,
253 d: D,
254 e: E,
255 f: F,
256 g: G,
257 h: H,
258 i: I,
259 j: J,
260 k: K,
261 l: L,
262 m: M,
263 n: N
264);
265args_impl!(
266 a: A,
267 b: B,
268 c: C,
269 d: D,
270 e: E,
271 f: F,
272 g: G,
273 h: H,
274 i: I,
275 j: J,
276 k: K,
277 l: L,
278 m: M,
279 n: N,
280 o: O
281);
282args_impl!(
283 a: A,
284 b: B,
285 c: C,
286 d: D,
287 e: E,
288 f: F,
289 g: G,
290 h: H,
291 i: I,
292 j: J,
293 k: K,
294 l: L,
295 m: M,
296 n: N,
297 o: O,
298 p: P
299);
300
301#[cfg(test)]
302mod tests {
303 use super::*;
304
305 use core::any::TypeId;
306 use core::ptr;
307
308 use crate::sel;
309
310 #[test]
311 fn convert_normally_noop() {
312 assert_eq!(
313 TypeId::of::<<i32 as ConvertArgument>::__Inner>(),
314 TypeId::of::<i32>()
315 );
316 assert_eq!(<i32 as ConvertArgument>::__from_defined_param(42), 42);
317 assert_eq!(unsafe { ConvertArgument::__into_argument(42i32).0 }, 42);
318 }
319
320 #[test]
321 fn convert_i8() {
322 assert_eq!(
323 TypeId::of::<<i8 as ConvertArgument>::__Inner>(),
324 TypeId::of::<i8>()
325 );
326 assert_eq!(<i8 as ConvertArgument>::__from_defined_param(-3), -3);
327 assert_eq!(unsafe { ConvertArgument::__into_argument(-3i32).0 }, -3);
328 }
329
330 #[test]
331 fn convert_bool() {
332 let receiver_ptr = ptr::null_mut::<AnyObject>();
333 let sel = sel!(foo);
334
335 assert!(!<bool as ConvertArgument>::__from_defined_param(Bool::NO));
336 assert!(<bool as ConvertArgument>::__from_defined_param(Bool::YES));
337 assert!(!unsafe {
338 <bool as ConvertReturn<()>>::convert_message_return(Bool::NO, receiver_ptr, sel)
339 });
340 assert!(unsafe {
341 <bool as ConvertReturn<()>>::convert_message_return(Bool::YES, receiver_ptr, sel)
342 });
343
344 assert!(!unsafe { ConvertArgument::__into_argument(false).0 }.as_bool());
345 assert!(unsafe { ConvertArgument::__into_argument(true).0 }.as_bool());
346 assert!(!ConvertReturn::<()>::convert_defined_return(false).as_bool());
347 assert!(ConvertReturn::<()>::convert_defined_return(true).as_bool());
348
349 #[cfg(all(target_vendor = "apple", target_os = "macos", target_arch = "x86_64"))]
350 assert_eq!(
351 <bool as ConvertArgument>::__Inner::ENCODING_ARGUMENT,
352 crate::encode::Encoding::Char,
353 );
354 }
355}