Skip to content

Commit b4fc5aa

Browse files
committed
Add get_rest() to Varargs
Added `offset_index` so that actual position of arguments is displayed in error messages.
1 parent 5ae565a commit b4fc5aa

File tree

1 file changed

+61
-9
lines changed

1 file changed

+61
-9
lines changed

gdnative-core/src/export/method.rs

+61-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::TryInto;
45
use std::fmt;
56
use std::marker::PhantomData;
67
use std::ops::{Bound, RangeBounds};
@@ -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,56 @@ 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+
/// Can be converted to any type that implements TryFrom<Varargs>.
372+
///
373+
/// # Errors
374+
/// Returns an error if the conversion fails.
375+
///
376+
/// # Examples
377+
/// ```ignore
378+
/// # fn foo(args: gdnative::export::Varargs) -> Result<(), Box<dyn std::error::Error>> {
379+
/// args.check_length(1..)?;
380+
/// let a: usize = args.get(0)?;
381+
/// let rest: Vec<i64> = args.get_rest(1)?;
382+
/// # Ok(())
383+
/// # }
384+
/// ```
385+
#[inline]
386+
pub fn get_rest<T>(&self, rest_index: usize) -> Result<T, <Varargs<'a> as TryInto<T>>::Error>
387+
where
388+
Varargs<'a>: TryInto<T>,
389+
{
390+
let relative_rest_index = rest_index;
391+
let actual_rest_index = rest_index + self.offset_index;
392+
393+
let rest = self.args.get(relative_rest_index..).unwrap_or_default();
394+
let varargs = Varargs::<'a> {
395+
idx: 0,
396+
args: rest,
397+
offset_index: actual_rest_index,
398+
};
399+
varargs.try_into()
400+
}
401+
402+
/// Get the varargs's offset index.
403+
#[inline]
404+
#[must_use]
405+
pub fn offset_index(&self) -> usize {
406+
self.offset_index
407+
}
357408
}
358409

359410
impl<'a> Iterator for Varargs<'a> {
@@ -600,10 +651,11 @@ impl<'r, 'a, T: FromVariant> ArgBuilder<'r, 'a, T> {
600651
#[inline]
601652
pub fn get(mut self) -> Result<T, ArgumentError<'a>> {
602653
self.get_optional_internal().and_then(|arg| {
654+
let actual_index = self.args.idx + self.args.offset_index;
603655
arg.ok_or(ArgumentError {
604656
site: self.site,
605657
kind: ArgumentErrorKind::Missing {
606-
idx: self.args.idx,
658+
idx: actual_index,
607659
name: self.name,
608660
},
609661
})
@@ -628,13 +680,13 @@ impl<'r, 'a, T: FromVariant> ArgBuilder<'r, 'a, T> {
628680
ty,
629681
..
630682
} = self;
631-
let idx = args.idx;
683+
let actual_index = args.idx + args.offset_index;
632684

633685
if let Some(arg) = args.next() {
634686
T::from_variant(arg).map(Some).map_err(|err| ArgumentError {
635687
site: *site,
636688
kind: ArgumentErrorKind::CannotConvert {
637-
idx,
689+
idx: actual_index,
638690
name: name.take(),
639691
value: arg,
640692
ty: ty

0 commit comments

Comments
 (0)