1use crate::{bindings::*, value::FromValue, *};
2
3pub struct CallInfo {
5 ci: _PBCallInfo,
6 mid: MethodId,
7 session: Session
8}
9
10impl CallInfo {
11 pub(crate) unsafe fn new(cls: pbclass, mid: MethodId, session: Session) -> Result<CallInfo> {
12 let mut ci = _PBCallInfo {
13 pArgs: NonNull::dangling(),
14 returnValue: NonNull::dangling(),
15 returnClass: NonNull::dangling()
16 };
17 let pbxr = ffi::pbsession_InitCallInfo(session.as_ptr(), cls, mid, (&mut ci).into());
18 if pbxr != PBXRESULT::OK {
19 return Err(pbxr);
20 }
21 Ok(CallInfo {
22 ci,
23 mid,
24 session
25 })
26 }
27 pub(crate) fn as_ptr(&self) -> pbcallinfo { (&self.ci).into() }
28 pub(crate) fn mid(&self) -> MethodId { self.mid }
29
30 pub fn as_ref(&self) -> CallInfoRef {
32 unsafe { CallInfoRef::from_ptr((&self.ci).into(), self.session.clone()) }
33 }
34
35 pub fn session(&self) -> &Session { &self.session }
37
38 pub fn arg(&self, idx: pbint) -> Value { self.args().get(idx) }
44
45 pub fn arg_count(&self) -> pbint { self.args().count() }
47
48 pub fn args(&self) -> Arguments {
50 unsafe { Arguments::from_ptr((&self.ci).into(), self.session.clone()) }
51 }
52
53 pub fn return_value(&self) -> Value {
55 unsafe { Value::from_ptr(self.ci.returnValue, self.session.clone()) }
56 }
57}
58
59impl Drop for CallInfo {
60 fn drop(&mut self) {
61 unsafe {
62 ffi::pbsession_FreeCallInfo(self.session.as_ptr(), (&self.ci).into());
63 }
64 }
65}
66
67pub struct CallInfoRef<'ci> {
69 ptr: pbcallinfo,
70 session: Session,
71 _marker: PhantomData<&'ci pbcallinfo>
72}
73
74impl<'ci> CallInfoRef<'ci> {
75 pub(crate) unsafe fn from_ptr(ptr: pbcallinfo, session: Session) -> CallInfoRef<'ci> {
76 CallInfoRef {
77 ptr,
78 session,
79 _marker: PhantomData
80 }
81 }
82 pub(crate) fn as_ptr(&self) -> pbcallinfo { self.ptr }
83 pub(crate) fn clone(&self) -> CallInfoRef<'ci> {
84 CallInfoRef {
85 ptr: self.ptr,
86 session: unsafe { self.session.clone() },
87 _marker: PhantomData
88 }
89 }
90
91 pub fn session(&self) -> &Session { &self.session }
93
94 pub fn arg(&self, idx: pbint) -> Value<'ci> { self.args().get(idx) }
100
101 pub fn arg_count(&self) -> pbint { self.args().count() }
103
104 pub fn args(&self) -> ArgumentsRef<'ci> {
106 unsafe { ArgumentsRef::from_ptr(self.ptr.as_ref().pArgs, self.session.clone()) }
107 }
108
109 pub fn return_value(&self) -> Value<'ci> {
111 unsafe { Value::from_ptr(self.ptr.as_ref().returnValue, self.session.clone()) }
112 }
113}
114
115pub trait FromCallInfo<'ci>: Sized {
117 fn from_callinfo(ci: &CallInfoRef<'ci>) -> Result<Self>;
118}
119
120pub trait FromArg<'ci>: Sized {
121 fn from_arg(
122 ci: &CallInfoRef<'ci>,
123 args: &ArgumentsRef<'ci>,
124 idx: &mut pbint,
125 complete: &mut bool
126 ) -> Result<Self>;
127}
128
129impl<'ci> FromArg<'ci> for CallInfoRef<'ci> {
130 fn from_arg(
131 ci: &CallInfoRef<'ci>,
132 _: &ArgumentsRef<'ci>,
133 _: &mut pbint,
134 complete: &mut bool
135 ) -> Result<Self> {
136 *complete = true;
137 Ok(ci.clone())
138 }
139}
140impl<'ci> FromArg<'ci> for ArgumentsRef<'ci> {
141 fn from_arg(
142 _: &CallInfoRef<'ci>,
143 args: &ArgumentsRef<'ci>,
144 _: &mut pbint,
145 complete: &mut bool
146 ) -> Result<Self> {
147 *complete = true;
148 Ok(args.clone())
149 }
150}
151impl FromArg<'_> for Session {
152 fn from_arg(ci: &CallInfoRef, _: &ArgumentsRef, _: &mut pbint, _: &mut bool) -> Result<Session> {
153 Ok(unsafe { ci.session().clone() })
154 }
155}
156
157impl<'ci, T: FromValue<'ci>> FromArg<'ci> for T {
158 fn from_arg(_: &CallInfoRef, args: &ArgumentsRef<'ci>, idx: &mut pbint, _: &mut bool) -> Result<Self> {
159 *idx += 1;
160 T::from_value(if *idx < args.count() {
161 Some(args.try_get(*idx)?)
162 } else {
163 None
164 })
165 }
166}
167
168#[rustfmt::skip]
169mod m {
170 use super::*;
171
172 macro_rules! tuple_from_ci {
174 ($($T:ident),+) => {
175 #[doc(hidden)]
176 impl<'ci,$($T:FromArg<'ci>),+> FromCallInfo<'ci> for ($($T,)+)
177 {
178 fn from_callinfo(ci: &CallInfoRef<'ci>) -> Result<Self> {
179 let args = ci.args();
180 let mut idx = -1;
181 let mut complete = false;
182 let rv = ($($T::from_arg(ci,&args,&mut idx,&mut complete)?,)+);
183 if !complete && idx + 1 < args.count() {
184 return Err(PBXRESULT::E_INVOKE_WRONG_NUM_ARGS);
185 }
186 Ok(rv)
187 }
188 }
189 }
190 }
191
192 #[doc(hidden)]
193 impl FromCallInfo<'_> for () {
194 fn from_callinfo(_: &CallInfoRef) -> Result<Self> { Ok(()) }
195 }
196
197 tuple_from_ci!(A);
198 tuple_from_ci!(A, B);
199 tuple_from_ci!(A, B, C);
200 tuple_from_ci!(A, B, C, D);
201 tuple_from_ci!(A, B, C, D, E);
202 tuple_from_ci!(A, B, C, D, E, F);
203 tuple_from_ci!(A, B, C, D, E, F, G);
204 tuple_from_ci!(A, B, C, D, E, F, G, H);
205 tuple_from_ci!(A, B, C, D, E, F, G, H, I);
206 tuple_from_ci!(A, B, C, D, E, F, G, H, I, J);
207 tuple_from_ci!(A, B, C, D, E, F, G, H, I, J, K);
208 tuple_from_ci!(A, B, C, D, E, F, G, H, I, J, K, L);
209 tuple_from_ci!(A, B, C, D, E, F, G, H, I, J, K, L, M);
210 tuple_from_ci!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
211 tuple_from_ci!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
212
213}