pbni/
callinfo.rs

1use crate::{bindings::*, value::FromValue, *};
2
3/// 过程调用上下文
4pub 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    /// 获取取引用对象
31    pub fn as_ref(&self) -> CallInfoRef {
32        unsafe { CallInfoRef::from_ptr((&self.ci).into(), self.session.clone()) }
33    }
34
35    /// 获取关联的`Session`
36    pub fn session(&self) -> &Session { &self.session }
37
38    /// 获取指定参数
39    ///
40    /// # Panics
41    ///
42    /// 索引越界时会触发Panic
43    pub fn arg(&self, idx: pbint) -> Value { self.args().get(idx) }
44
45    /// 获取参数数量
46    pub fn arg_count(&self) -> pbint { self.args().count() }
47
48    /// 获取参数列表对象
49    pub fn args(&self) -> Arguments {
50        unsafe { Arguments::from_ptr((&self.ci).into(), self.session.clone()) }
51    }
52
53    /// 获取返回值对象
54    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
67/// 调用上下文引用
68pub 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    /// 获取关联的`Session`
92    pub fn session(&self) -> &Session { &self.session }
93
94    /// 获取指定参数
95    ///
96    /// # Panics
97    ///
98    /// 索引越界时会触发Panic
99    pub fn arg(&self, idx: pbint) -> Value<'ci> { self.args().get(idx) }
100
101    /// 获取参数数量
102    pub fn arg_count(&self) -> pbint { self.args().count() }
103
104    /// 获取参数列表对象
105    pub fn args(&self) -> ArgumentsRef<'ci> {
106        unsafe { ArgumentsRef::from_ptr(self.ptr.as_ref().pArgs, self.session.clone()) }
107    }
108
109    /// 获取返回值对象
110    pub fn return_value(&self) -> Value<'ci> {
111        unsafe { Value::from_ptr(self.ptr.as_ref().returnValue, self.session.clone()) }
112    }
113}
114
115/// 提取参数列表
116pub 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    /// 提取CallInfo参数为tuple
173    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}