pbni/
arguments.rs

1use crate::{bindings::*, *};
2use std::ptr;
3
4/// 过程调用参数列表对象的引用,此对象可以添加参数
5///
6/// # Examples
7///
8/// ```no_run
9/// ci.args.add_long(123);
10/// ci.args.add_long(None); //添加NULL值
11/// ```
12pub struct Arguments<'args> {
13    ci: pbcallinfo,
14    count: pbint,
15    session: Session,
16    _marker: PhantomData<&'args pbcallinfo>
17}
18
19impl<'args> Arguments<'args> {
20    pub(crate) unsafe fn from_ptr(ci: pbcallinfo, session: Session) -> Arguments<'args> {
21        let count = ffi::pbargs_GetCount(ci.as_ref().pArgs);
22        Arguments {
23            ci,
24            count,
25            session,
26            _marker: PhantomData
27        }
28    }
29
30    /// 获取引用对象
31    pub fn as_ref(&self) -> ArgumentsRef {
32        unsafe { ArgumentsRef::from_ptr(self.ci.as_ref().pArgs, self.session.clone()) }
33    }
34
35    /// 获取引用元素迭代器
36    pub fn iter(&self) -> ArgumentsIter {
37        let args = unsafe { ArgumentsRef::from_ptr(self.ci.as_ref().pArgs, self.session.clone()) };
38        ArgumentsIter {
39            args,
40            idx: 0
41        }
42    }
43
44    /// 参数数量
45    pub fn count(&self) -> pbint { self.count }
46
47    /// 获取参数值
48    ///
49    /// # Panics
50    ///
51    /// 索引越界时会触发Panic
52    pub fn get(&self, index: pbint) -> Value<'args> {
53        if let Ok(val) = self.try_get(index) {
54            val
55        } else {
56            panic!("arg index {} is out of bound {}", index, self.count)
57        }
58    }
59
60    /// 尝试获取参数值
61    pub fn try_get(&self, index: pbint) -> Result<Value<'args>> {
62        if index < 0 || index >= self.count {
63            return Err(PBXRESULT::E_ARRAY_INDEX_OUTOF_BOUNDS);
64        }
65        unsafe { Ok(Value::from_ptr(ffi::pbargs_GetAt(self.ci.as_ref().pArgs, index), self.session.clone())) }
66    }
67
68    /// 添加`int`类型参数
69    pub fn add_int(&mut self, value: impl Into<Option<pbint>>) -> Result<()> {
70        let value = value.into();
71        unsafe {
72            let pbxr = ffi::pbsession_AddIntArgument(
73                self.session.as_ptr(),
74                self.ci,
75                value.unwrap_or_default(),
76                value.is_none().into()
77            );
78            if pbxr.is_ok() {
79                self.count += 1;
80            }
81            pbxr.into()
82        }
83    }
84
85    /// 添加`uint`类型参数
86    pub fn add_uint(&mut self, value: impl Into<Option<pbuint>>) -> Result<()> {
87        let value = value.into();
88        unsafe {
89            let pbxr = ffi::pbsession_AddUintArgument(
90                self.session.as_ptr(),
91                self.ci,
92                value.unwrap_or_default(),
93                value.is_none().into()
94            );
95            if pbxr.is_ok() {
96                self.count += 1;
97            }
98            pbxr.into()
99        }
100    }
101
102    /// 添加`long`类型参数
103    pub fn add_long(&mut self, value: impl Into<Option<pblong>>) -> Result<()> {
104        let value = value.into();
105        unsafe {
106            let pbxr = ffi::pbsession_AddLongArgument(
107                self.session.as_ptr(),
108                self.ci,
109                value.unwrap_or_default(),
110                value.is_none().into()
111            );
112            if pbxr.is_ok() {
113                self.count += 1;
114            }
115            pbxr.into()
116        }
117    }
118
119    /// 添加`ulong`类型参数
120    pub fn add_ulong(&mut self, value: impl Into<Option<pbulong>>) -> Result<()> {
121        let value = value.into();
122        unsafe {
123            let pbxr = ffi::pbsession_AddUlongArgument(
124                self.session.as_ptr(),
125                self.ci,
126                value.unwrap_or_default(),
127                value.is_none().into()
128            );
129            if pbxr.is_ok() {
130                self.count += 1;
131            }
132            pbxr.into()
133        }
134    }
135
136    /// 添加`longlong`类型参数
137    pub fn add_longlong(&mut self, value: impl Into<Option<pblonglong>>) -> Result<()> {
138        let value = value.into();
139        unsafe {
140            let pbxr = ffi::pbsession_AddLongLongArgument(
141                self.session.as_ptr(),
142                self.ci,
143                value.unwrap_or_default(),
144                value.is_none().into()
145            );
146            if pbxr.is_ok() {
147                self.count += 1;
148            }
149            pbxr.into()
150        }
151    }
152
153    /// 添加`real`类型参数
154    pub fn add_real(&mut self, value: impl Into<Option<pbreal>>) -> Result<()> {
155        let value = value.into();
156        unsafe {
157            let pbxr = ffi::pbsession_AddRealArgument(
158                self.session.as_ptr(),
159                self.ci,
160                value.unwrap_or_default(),
161                value.is_none().into()
162            );
163            if pbxr.is_ok() {
164                self.count += 1;
165            }
166            pbxr.into()
167        }
168    }
169
170    /// 添加`double`类型参数
171    pub fn add_double(&mut self, value: impl Into<Option<pbdouble>>) -> Result<()> {
172        let value = value.into();
173        unsafe {
174            let pbxr = ffi::pbsession_AddDoubleArgument(
175                self.session.as_ptr(),
176                self.ci,
177                value.unwrap_or_default(),
178                value.is_none().into()
179            );
180            if pbxr.is_ok() {
181                self.count += 1;
182            }
183            pbxr.into()
184        }
185    }
186
187    /// 添加`decimal`类型参数
188    #[cfg(feature = "decimal")]
189    pub fn add_dec(&mut self, value: impl Into<Option<Decimal>>) -> Result<()> {
190        unsafe {
191            let value = value.into().map(|v| self.session.new_pbdec(v));
192            let pbxr = ffi::pbsession_AddDecArgument(
193                self.session.as_ptr(),
194                self.ci,
195                value.unwrap_or(NonNull::new_unchecked(0 as _)),
196                value.is_none().into()
197            );
198            if pbxr.is_ok() {
199                self.count += 1;
200            }
201            pbxr.into()
202        }
203    }
204
205    /// 添加`string`类型参数
206    pub fn add_string<T, D>(&mut self, value: T) -> Result<()>
207    where
208        T: Into<Option<D>>,
209        D: AsPBStr
210    {
211        let value = value.into();
212        unsafe {
213            let value = value.map(|v| v.as_pbstr().as_ptr());
214            let pbxr = ffi::pbsession_AddStringArgument(
215                self.session.as_ptr(),
216                self.ci,
217                value.unwrap_or(ptr::null()),
218                value.is_none().into()
219            );
220            if pbxr.is_ok() {
221                self.count += 1;
222            }
223            pbxr.into()
224        }
225    }
226
227    /// 添加`boolean`类型参数
228    pub fn add_bool(&mut self, value: impl Into<Option<bool>>) -> Result<()> {
229        let value = value.into();
230        unsafe {
231            let pbxr = ffi::pbsession_AddBoolArgument(
232                self.session.as_ptr(),
233                self.ci,
234                value.unwrap_or_default().into(),
235                value.is_none().into()
236            );
237            if pbxr.is_ok() {
238                self.count += 1;
239            }
240            pbxr.into()
241        }
242    }
243
244    /// 添加`blob`类型参数
245    pub fn add_blob<'a>(&mut self, value: impl Into<Option<&'a [u8]>>) -> Result<()> {
246        let value = value.into();
247        if let Some(ref value) = value {
248            if value.is_empty() {
249                return Err(PBXRESULT::E_OUTOF_MEMORY);
250            }
251        }
252        unsafe {
253            let value = value.map(|v| self.session.new_pbblob(v));
254            let pbxr = ffi::pbsession_AddBlobArgument(
255                self.session.as_ptr(),
256                self.ci,
257                value.unwrap_or(NonNull::new_unchecked(0 as _)),
258                value.is_none().into()
259            );
260            if pbxr.is_ok() {
261                self.count += 1;
262            }
263            pbxr.into()
264        }
265    }
266
267    /// 添加`date`类型参数
268    #[cfg(feature = "datetime")]
269    pub fn add_date(&mut self, value: impl Into<Option<NaiveDate>>) -> Result<()> {
270        unsafe {
271            let value = value.into().map(|v| self.session.new_pbdate(v));
272            let pbxr = ffi::pbsession_AddDateArgument(
273                self.session.as_ptr(),
274                self.ci,
275                value.unwrap_or(NonNull::new_unchecked(0 as _)),
276                value.is_none().into()
277            );
278            if pbxr.is_ok() {
279                self.count += 1;
280            }
281            pbxr.into()
282        }
283    }
284
285    /// 添加`time`类型参数
286    #[cfg(feature = "datetime")]
287    pub fn add_time(&mut self, value: impl Into<Option<NaiveTime>>) -> Result<()> {
288        unsafe {
289            let value = value.into().map(|v| self.session.new_pbtime(v));
290            let pbxr = ffi::pbsession_AddTimeArgument(
291                self.session.as_ptr(),
292                self.ci,
293                value.unwrap_or(NonNull::new_unchecked(0 as _)),
294                value.is_none().into()
295            );
296            if pbxr.is_ok() {
297                self.count += 1;
298            }
299            pbxr.into()
300        }
301    }
302
303    /// 添加`datetime`类型参数
304    #[cfg(feature = "datetime")]
305    pub fn add_datetime(&mut self, value: impl Into<Option<NaiveDateTime>>) -> Result<()> {
306        unsafe {
307            let value = value.into().map(|v| self.session.new_pbdatetime(v));
308            let pbxr = ffi::pbsession_AddDateTimeArgument(
309                self.session.as_ptr(),
310                self.ci,
311                value.unwrap_or(NonNull::new_unchecked(0 as _)),
312                value.is_none().into()
313            );
314            if pbxr.is_ok() {
315                self.count += 1;
316            }
317            pbxr.into()
318        }
319    }
320
321    /// 添加`char`类型参数
322    pub fn add_char(&mut self, value: impl Into<Option<PBChar>>) -> Result<()> {
323        let value = value.into();
324        unsafe {
325            let pbxr = ffi::pbsession_AddCharArgument(
326                self.session.as_ptr(),
327                self.ci,
328                value.unwrap_or_default(),
329                value.is_none().into()
330            );
331            if pbxr.is_ok() {
332                self.count += 1;
333            }
334            pbxr.into()
335        }
336    }
337
338    /// 添加对象类型参数
339    pub fn add_object<'a, 'b: 'a>(&mut self, value: impl Into<Option<&'a Object<'b>>>) -> Result<()> {
340        unsafe {
341            let value = value.into().map(|v| v.as_ptr());
342            let pbxr = ffi::pbsession_AddObjectArgument(
343                self.session.as_ptr(),
344                self.ci,
345                value.unwrap_or(NonNull::new_unchecked(0 as _)),
346                value.is_none().into()
347            );
348            if pbxr.is_ok() {
349                self.count += 1;
350            }
351            pbxr.into()
352        }
353    }
354
355    /// 添加数组类型参数
356    pub fn add_array<'a, 'b: 'a>(&mut self, value: impl Into<Option<&'a Array<'b>>>) -> Result<()> {
357        unsafe {
358            let value = value.into().map(|v| v.as_ptr());
359            let pbxr = ffi::pbsession_AddArrayArgument(
360                self.session.as_ptr(),
361                self.ci,
362                value.unwrap_or(NonNull::new_unchecked(0 as _)),
363                value.is_none().into()
364            );
365            if pbxr.is_ok() {
366                self.count += 1;
367            }
368            pbxr.into()
369        }
370    }
371}
372
373/// 过程调用参数列表对象的引用,此对象不可增加参数
374pub struct ArgumentsRef<'args> {
375    ptr: pbarguments,
376    count: pbint,
377    session: Session,
378    _marker: PhantomData<&'args pbarguments>
379}
380
381impl<'args> ArgumentsRef<'args> {
382    pub(crate) unsafe fn from_ptr(ptr: pbarguments, session: Session) -> ArgumentsRef<'args> {
383        let count = ffi::pbargs_GetCount(ptr);
384        ArgumentsRef {
385            ptr,
386            count,
387            session,
388            _marker: PhantomData
389        }
390    }
391    pub(crate) fn clone(&self) -> ArgumentsRef<'args> {
392        ArgumentsRef {
393            ptr: self.ptr,
394            count: self.count,
395            session: unsafe { self.session.clone() },
396            _marker: PhantomData
397        }
398    }
399
400    /// 获取引用元素迭代器
401    pub fn iter(&self) -> ArgumentsIter {
402        let args = unsafe { ArgumentsRef::from_ptr(self.ptr, self.session.clone()) };
403        ArgumentsIter {
404            args,
405            idx: 0
406        }
407    }
408
409    /// 参数数量
410    pub fn count(&self) -> pbint { self.count }
411
412    /// 获取参数值
413    ///
414    /// # Panics
415    ///
416    /// 索引越界时会触发Panic
417    pub fn get(&self, index: pbint) -> Value<'args> {
418        if let Ok(val) = self.try_get(index) {
419            val
420        } else {
421            panic!("arg index {} is out of bound {}", index, self.count)
422        }
423    }
424
425    /// 尝试获取参数值
426    pub fn try_get(&self, index: pbint) -> Result<Value<'args>> {
427        if index < 0 || index >= self.count {
428            return Err(PBXRESULT::E_ARRAY_INDEX_OUTOF_BOUNDS);
429        }
430        unsafe { Ok(Value::from_ptr(ffi::pbargs_GetAt(self.ptr, index), self.session.clone())) }
431    }
432}
433
434///参数迭代器
435pub struct ArgumentsIter<'args> {
436    args: ArgumentsRef<'args>,
437    idx: pbint
438}
439
440impl<'args> Iterator for ArgumentsIter<'args> {
441    type Item = Value<'args>;
442    fn next(&mut self) -> Option<Self::Item> {
443        let idx = self.idx;
444        self.idx += 1;
445        if idx < self.args.count() {
446            Some(self.args.get(idx))
447        } else {
448            None
449        }
450    }
451    fn size_hint(&self) -> (usize, Option<usize>) { (0, Some(self.args.count() as usize)) }
452}
453
454impl<'args> IntoIterator for Arguments<'args> {
455    type Item = Value<'args>;
456    type IntoIter = ArgumentsIter<'args>;
457
458    fn into_iter(self) -> Self::IntoIter {
459        let args = unsafe { ArgumentsRef::from_ptr(self.ci.as_ref().pArgs, self.session.clone()) };
460        ArgumentsIter {
461            args,
462            idx: 0
463        }
464    }
465}
466
467impl<'args> IntoIterator for ArgumentsRef<'args> {
468    type Item = Value<'args>;
469    type IntoIter = ArgumentsIter<'args>;
470
471    fn into_iter(self) -> Self::IntoIter {
472        ArgumentsIter {
473            args: self,
474            idx: 0
475        }
476    }
477}