Skip to content

Commit c2fe383

Browse files
committed
Add get_rest() to Varrags
Added offset_index so that actual position of arguments is displayed in error messages.
1 parent d68ff08 commit c2fe383

File tree

1 file changed

+57
-9
lines changed

1 file changed

+57
-9
lines changed

gdnative-core/src/export/method.rs

+57-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Method registration
22
33
use std::borrow::Cow;
4+
use std::convert::TryFrom;
45
use std::fmt;
56
use std::marker::PhantomData;
67
use std::ops::Bound;
@@ -214,6 +215,7 @@ impl<C: NativeClass, F: StaticArgsMethod<C>> Method<C> for StaticArgs<F> {
214215
pub struct Varargs<'a> {
215216
idx: usize,
216217
args: &'a [&'a Variant],
218+
offset_index: usize,
217219
}
218220

219221
impl<'a> Varargs<'a> {
@@ -283,7 +285,11 @@ impl<'a> Varargs<'a> {
283285
pub unsafe fn from_sys(num_args: libc::c_int, args: *mut *mut sys::godot_variant) -> Self {
284286
let args = std::slice::from_raw_parts(args, num_args as usize);
285287
let args = std::mem::transmute::<&[*mut sys::godot_variant], &[&Variant]>(args);
286-
Self { idx: 0, args }
288+
Self {
289+
idx: 0,
290+
args,
291+
offset_index: 0,
292+
}
287293
}
288294

289295
/// Check the length of arguments.
@@ -317,14 +323,17 @@ impl<'a> Varargs<'a> {
317323
/// ```
318324
#[inline]
319325
pub fn get<T: FromVariant>(&self, index: usize) -> Result<T, ArgumentTypeError> {
320-
match self.args.get(index) {
326+
let relative_index = index;
327+
let actual_index = index + self.offset_index;
328+
329+
match self.args.get(relative_index) {
321330
Some(v) => match T::from_variant(v) {
322331
Ok(ok) => Ok(ok),
323-
Err(err) => Err(ArgumentTypeError::new(index, err)),
332+
Err(err) => Err(ArgumentTypeError::new(actual_index, err)),
324333
},
325334
None => {
326335
let err = FromVariantError::Custom("Argument is not set".to_owned());
327-
Err(ArgumentTypeError::new(index, err))
336+
Err(ArgumentTypeError::new(actual_index, err))
328337
}
329338
}
330339
}
@@ -346,14 +355,52 @@ impl<'a> Varargs<'a> {
346355
/// ```
347356
#[inline]
348357
pub fn get_opt<T: FromVariant>(&self, index: usize) -> Result<Option<T>, ArgumentTypeError> {
349-
match self.args.get(index) {
358+
let relative_index = index;
359+
let actual_index = index + self.offset_index;
360+
361+
match self.args.get(relative_index) {
350362
Some(v) => match T::from_variant(v) {
351363
Ok(ok) => Ok(Some(ok)),
352-
Err(err) => Err(ArgumentTypeError::new(index, err)),
364+
Err(err) => Err(ArgumentTypeError::new(actual_index, err)),
353365
},
354366
None => Ok(None),
355367
}
356368
}
369+
370+
/// Returns the type-converted value from the specified argument position.
371+
///
372+
/// # Errors
373+
/// Returns an error if the conversion fails.
374+
///
375+
/// # Examples
376+
/// ```ignore
377+
/// # fn call(args: gdnative::export::Varargs) -> Result<(), Box<dyn std::error::Error>> {
378+
/// args.check_length(1..)?;
379+
/// let a: usize = args.get(0)?;
380+
/// let rest: Vec<i64> = args.get_rest(1)?;
381+
/// # Ok(())
382+
/// # }
383+
/// ```
384+
#[inline]
385+
pub fn get_rest<T: TryFrom<Varargs<'a>>>(&self, rest_index: usize) -> Result<T, T::Error> {
386+
let relative_rest_index = rest_index;
387+
let actual_rest_index = rest_index + self.offset_index;
388+
389+
let rest = self.args.get(relative_rest_index..).unwrap_or_default();
390+
let varargs = Varargs::<'a> {
391+
idx: 0,
392+
args: rest,
393+
offset_index: actual_rest_index,
394+
};
395+
T::try_from(varargs)
396+
}
397+
398+
/// Get the varargs's offset index.
399+
#[inline]
400+
#[must_use]
401+
pub fn offset_index(&self) -> usize {
402+
self.offset_index
403+
}
357404
}
358405

359406
impl<'a> Iterator for Varargs<'a> {
@@ -711,10 +758,11 @@ impl<'r, 'a, T: FromVariant> ArgBuilder<'r, 'a, T> {
711758
#[inline]
712759
pub fn get(mut self) -> Result<T, ArgumentError<'a>> {
713760
self.get_optional_internal().and_then(|arg| {
761+
let actual_index = self.args.idx + self.args.offset_index;
714762
arg.ok_or(ArgumentError {
715763
site: self.site,
716764
kind: ArgumentErrorKind::Missing {
717-
idx: self.args.idx,
765+
idx: actual_index,
718766
name: self.name,
719767
},
720768
})
@@ -739,13 +787,13 @@ impl<'r, 'a, T: FromVariant> ArgBuilder<'r, 'a, T> {
739787
ty,
740788
..
741789
} = self;
742-
let idx = args.idx;
790+
let actual_index = args.idx + args.offset_index;
743791

744792
if let Some(arg) = args.next() {
745793
T::from_variant(arg).map(Some).map_err(|err| ArgumentError {
746794
site: *site,
747795
kind: ArgumentErrorKind::CannotConvert {
748-
idx,
796+
idx: actual_index,
749797
name: name.take(),
750798
value: arg,
751799
ty: ty

0 commit comments

Comments
 (0)