Add ArgCount
This commit is contained in:
parent
f93aadd0dd
commit
c3b91562d1
311
crates/bevy_reflect/src/func/args/count.rs
Normal file
311
crates/bevy_reflect/src/func/args/count.rs
Normal file
@ -0,0 +1,311 @@
|
|||||||
|
use crate::func::args::ArgCountOutOfBoundsError;
|
||||||
|
use core::fmt::{Debug, Formatter};
|
||||||
|
|
||||||
|
/// A container for zero or more argument counts for a function.
|
||||||
|
///
|
||||||
|
/// For most functions, this will contain a single count,
|
||||||
|
/// however, overloaded functions may contain more.
|
||||||
|
///
|
||||||
|
/// # Maximum Argument Count
|
||||||
|
///
|
||||||
|
/// The maximum number of arguments that can be represented by this struct is 63,
|
||||||
|
/// as given by [`ArgCount::MAX_COUNT`].
|
||||||
|
/// The reason for this is that all counts are stored internally as a single `u64`
|
||||||
|
/// with each bit representing a specific count based on its bit index.
|
||||||
|
///
|
||||||
|
/// This allows for a smaller memory footprint and faster lookups compared to a
|
||||||
|
/// `HashSet` or `Vec` of possible counts.
|
||||||
|
/// It's also more appropriate for representing the argument counts of a function
|
||||||
|
/// given that most functions will not have more than a few arguments.
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct ArgCount {
|
||||||
|
/// The bits representing the argument counts.
|
||||||
|
///
|
||||||
|
/// Each bit represents a specific count based on its bit index.
|
||||||
|
bits: u64,
|
||||||
|
/// The total number of argument counts.
|
||||||
|
len: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ArgCount {
|
||||||
|
/// The maximum number of arguments that can be represented by this struct.
|
||||||
|
pub const MAX_COUNT: usize = u64::BITS as usize - 1;
|
||||||
|
|
||||||
|
/// Create a new [`ArgCount`] with the given count.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Returns an error if the count is greater than [`Self::MAX_COUNT`].
|
||||||
|
pub fn new(count: usize) -> Result<Self, ArgCountOutOfBoundsError> {
|
||||||
|
Ok(Self {
|
||||||
|
bits: 1 << Self::try_to_u8(count)?,
|
||||||
|
len: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds the given count to this [`ArgCount`].
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the count is greater than [`Self::MAX_COUNT`].
|
||||||
|
pub fn add(&mut self, count: usize) {
|
||||||
|
self.try_add(count).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Attempts to add the given count to this [`ArgCount`].
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Returns an error if the count is greater than [`Self::MAX_COUNT`].
|
||||||
|
pub fn try_add(&mut self, count: usize) -> Result<(), ArgCountOutOfBoundsError> {
|
||||||
|
let count = Self::try_to_u8(count)?;
|
||||||
|
|
||||||
|
if !self.contains_unchecked(count) {
|
||||||
|
self.len += 1;
|
||||||
|
self.bits |= 1 << count;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Removes the given count from this [`ArgCount`].
|
||||||
|
pub fn remove(&mut self, count: usize) {
|
||||||
|
self.try_remove(count).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Attempts to remove the given count from this [`ArgCount`].
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Returns an error if the count is greater than [`Self::MAX_COUNT`].
|
||||||
|
pub fn try_remove(&mut self, count: usize) -> Result<(), ArgCountOutOfBoundsError> {
|
||||||
|
let count = Self::try_to_u8(count)?;
|
||||||
|
|
||||||
|
if self.contains_unchecked(count) {
|
||||||
|
self.len -= 1;
|
||||||
|
self.bits &= !(1 << count);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if this [`ArgCount`] contains the given count.
|
||||||
|
pub fn contains(&self, count: usize) -> bool {
|
||||||
|
count < usize::BITS as usize && (self.bits >> count) & 1 == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the total number of argument counts that this [`ArgCount`] contains.
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.len as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if this [`ArgCount`] contains no argument counts.
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.len == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns an iterator over the argument counts in this [`ArgCount`].
|
||||||
|
pub fn iter(&self) -> ArgCountIter {
|
||||||
|
ArgCountIter {
|
||||||
|
count: *self,
|
||||||
|
index: 0,
|
||||||
|
found: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if this [`ArgCount`] contains the given count without any bounds checking.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the count is greater than [`Self::MAX_COUNT`].
|
||||||
|
fn contains_unchecked(&self, count: u8) -> bool {
|
||||||
|
(self.bits >> count) & 1 == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Attempts to convert the given count to a `u8` within the bounds of the [maximum count].
|
||||||
|
///
|
||||||
|
/// [maximum count]: Self::MAX_COUNT
|
||||||
|
fn try_to_u8(count: usize) -> Result<u8, ArgCountOutOfBoundsError> {
|
||||||
|
if count > Self::MAX_COUNT {
|
||||||
|
Err(ArgCountOutOfBoundsError(count))
|
||||||
|
} else {
|
||||||
|
Ok(count as u8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Defaults this [`ArgCount`] to empty.
|
||||||
|
///
|
||||||
|
/// This means that it contains no argument counts, including zero.
|
||||||
|
impl Default for ArgCount {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { bits: 0, len: 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for ArgCount {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||||
|
f.debug_set().entries(self.iter()).finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An iterator for the argument counts in an [`ArgCount`].
|
||||||
|
pub struct ArgCountIter {
|
||||||
|
count: ArgCount,
|
||||||
|
index: u8,
|
||||||
|
found: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for ArgCountIter {
|
||||||
|
type Item = usize;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
loop {
|
||||||
|
if self.index as usize > ArgCount::MAX_COUNT {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.found == self.count.len {
|
||||||
|
// All counts have been found
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.count.contains_unchecked(self.index) {
|
||||||
|
self.index += 1;
|
||||||
|
self.found += 1;
|
||||||
|
return Some(self.index as usize - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
|
(self.count.len(), Some(self.count.len()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExactSizeIterator for ArgCountIter {}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_default_to_empty() {
|
||||||
|
let count = ArgCount::default();
|
||||||
|
|
||||||
|
assert_eq!(count.len(), 0);
|
||||||
|
assert!(count.is_empty());
|
||||||
|
|
||||||
|
assert!(!count.contains(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_construct_with_count() {
|
||||||
|
let count = ArgCount::new(3).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(count.len(), 1);
|
||||||
|
assert!(!count.is_empty());
|
||||||
|
|
||||||
|
assert!(count.contains(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_add_count() {
|
||||||
|
let mut count = ArgCount::default();
|
||||||
|
count.add(3);
|
||||||
|
|
||||||
|
assert_eq!(count.len(), 1);
|
||||||
|
|
||||||
|
assert!(count.contains(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_add_multiple_counts() {
|
||||||
|
let mut count = ArgCount::default();
|
||||||
|
count.add(3);
|
||||||
|
count.add(5);
|
||||||
|
count.add(7);
|
||||||
|
|
||||||
|
assert_eq!(count.len(), 3);
|
||||||
|
|
||||||
|
assert!(!count.contains(0));
|
||||||
|
assert!(!count.contains(1));
|
||||||
|
assert!(!count.contains(2));
|
||||||
|
|
||||||
|
assert!(count.contains(3));
|
||||||
|
assert!(count.contains(5));
|
||||||
|
assert!(count.contains(7));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_add_idempotently() {
|
||||||
|
let mut count = ArgCount::default();
|
||||||
|
count.add(3);
|
||||||
|
count.add(3);
|
||||||
|
|
||||||
|
assert_eq!(count.len(), 1);
|
||||||
|
assert!(count.contains(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_remove_count() {
|
||||||
|
let mut count = ArgCount::default();
|
||||||
|
count.add(3);
|
||||||
|
|
||||||
|
assert_eq!(count.len(), 1);
|
||||||
|
assert!(count.contains(3));
|
||||||
|
|
||||||
|
count.remove(3);
|
||||||
|
|
||||||
|
assert_eq!(count.len(), 0);
|
||||||
|
assert!(!count.contains(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_allow_removeting_nonexistent_count() {
|
||||||
|
let mut count = ArgCount::default();
|
||||||
|
|
||||||
|
assert_eq!(count.len(), 0);
|
||||||
|
assert!(!count.contains(3));
|
||||||
|
|
||||||
|
count.remove(3);
|
||||||
|
|
||||||
|
assert_eq!(count.len(), 0);
|
||||||
|
assert!(!count.contains(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_iterate_over_counts() {
|
||||||
|
let mut count = ArgCount::default();
|
||||||
|
count.add(3);
|
||||||
|
count.add(5);
|
||||||
|
count.add(7);
|
||||||
|
|
||||||
|
let mut iter = count.iter();
|
||||||
|
|
||||||
|
assert_eq!(iter.len(), 3);
|
||||||
|
|
||||||
|
assert_eq!(iter.next(), Some(3));
|
||||||
|
assert_eq!(iter.next(), Some(5));
|
||||||
|
assert_eq!(iter.next(), Some(7));
|
||||||
|
assert_eq!(iter.next(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_return_error_for_out_of_bounds_count() {
|
||||||
|
let count = ArgCount::new(64);
|
||||||
|
assert_eq!(count, Err(ArgCountOutOfBoundsError(64)));
|
||||||
|
|
||||||
|
let mut count = ArgCount::default();
|
||||||
|
assert_eq!(count.try_add(64), Err(ArgCountOutOfBoundsError(64)));
|
||||||
|
assert_eq!(count.try_remove(64), Err(ArgCountOutOfBoundsError(64)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_return_false_for_out_of_bounds_contains() {
|
||||||
|
let count = ArgCount::default();
|
||||||
|
assert!(!count.contains(64));
|
||||||
|
}
|
||||||
|
}
|
@ -32,3 +32,8 @@ pub enum ArgError {
|
|||||||
#[error("expected an argument but received none")]
|
#[error("expected an argument but received none")]
|
||||||
EmptyArgList,
|
EmptyArgList,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The given argument count is out of bounds.
|
||||||
|
#[derive(Debug, Error, PartialEq)]
|
||||||
|
#[error("argument count out of bounds: {0}")]
|
||||||
|
pub struct ArgCountOutOfBoundsError(pub usize);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
//! [`DynamicFunctionMut`]: crate::func::DynamicFunctionMut
|
//! [`DynamicFunctionMut`]: crate::func::DynamicFunctionMut
|
||||||
|
|
||||||
pub use arg::*;
|
pub use arg::*;
|
||||||
|
pub use count::*;
|
||||||
pub use error::*;
|
pub use error::*;
|
||||||
pub use from_arg::*;
|
pub use from_arg::*;
|
||||||
pub use info::*;
|
pub use info::*;
|
||||||
@ -11,6 +12,7 @@ pub use list::*;
|
|||||||
pub use ownership::*;
|
pub use ownership::*;
|
||||||
|
|
||||||
mod arg;
|
mod arg;
|
||||||
|
mod count;
|
||||||
mod error;
|
mod error;
|
||||||
mod from_arg;
|
mod from_arg;
|
||||||
mod info;
|
mod info;
|
||||||
|
@ -2,7 +2,9 @@ use crate::{
|
|||||||
self as bevy_reflect,
|
self as bevy_reflect,
|
||||||
__macro_exports::RegisterForReflection,
|
__macro_exports::RegisterForReflection,
|
||||||
func::{
|
func::{
|
||||||
args::ArgList, dynamic_function_internal::DynamicFunctionInternal, info::FunctionInfo,
|
args::{ArgCount, ArgList},
|
||||||
|
dynamic_function_internal::DynamicFunctionInternal,
|
||||||
|
info::FunctionInfo,
|
||||||
DynamicFunctionMut, Function, FunctionOverloadError, FunctionResult, IntoFunction,
|
DynamicFunctionMut, Function, FunctionOverloadError, FunctionResult, IntoFunction,
|
||||||
IntoFunctionMut,
|
IntoFunctionMut,
|
||||||
},
|
},
|
||||||
@ -13,7 +15,6 @@ use crate::{
|
|||||||
use alloc::{borrow::Cow, boxed::Box, sync::Arc};
|
use alloc::{borrow::Cow, boxed::Box, sync::Arc};
|
||||||
use bevy_reflect_derive::impl_type_path;
|
use bevy_reflect_derive::impl_type_path;
|
||||||
use core::fmt::{Debug, Formatter};
|
use core::fmt::{Debug, Formatter};
|
||||||
use core::ops::RangeInclusive;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
use alloc::{boxed::Box, format, vec};
|
use alloc::{boxed::Box, format, vec};
|
||||||
@ -83,7 +84,10 @@ impl<'env> DynamicFunction<'env> {
|
|||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics if no [`SignatureInfo`] is provided or if the conversion to [`FunctionInfo`] fails.
|
/// This function may panic for any of the following reasons:
|
||||||
|
/// - No [`SignatureInfo`] is provided.
|
||||||
|
/// - A provided [`SignatureInfo`] has more arguments than [`ArgCount::MAX_COUNT`].
|
||||||
|
/// - The conversion to [`FunctionInfo`] fails.
|
||||||
///
|
///
|
||||||
/// [calling]: crate::func::dynamic_function::DynamicFunction::call
|
/// [calling]: crate::func::dynamic_function::DynamicFunction::call
|
||||||
/// [`SignatureInfo`]: crate::func::SignatureInfo
|
/// [`SignatureInfo`]: crate::func::SignatureInfo
|
||||||
@ -309,27 +313,25 @@ impl<'env> DynamicFunction<'env> {
|
|||||||
pub fn is_overloaded(&self) -> bool {
|
pub fn is_overloaded(&self) -> bool {
|
||||||
self.internal.is_overloaded()
|
self.internal.is_overloaded()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the number of arguments the function expects.
|
/// Returns the number of arguments the function expects.
|
||||||
///
|
///
|
||||||
/// For [overloaded] functions that can have a variable number of arguments,
|
/// For [overloaded] functions that can have a variable number of arguments,
|
||||||
/// this will return the minimum and maximum number of arguments.
|
/// this will contain the full set of counts for all signatures.
|
||||||
///
|
|
||||||
/// Otherwise, the range will have the same start and end.
|
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use bevy_reflect::func::IntoFunction;
|
/// # use bevy_reflect::func::IntoFunction;
|
||||||
/// let add = (|a: i32, b: i32| a + b).into_function();
|
/// let add = (|a: i32, b: i32| a + b).into_function();
|
||||||
/// assert_eq!(add.arg_count(), 2..=2);
|
/// assert!(add.arg_count().contains(2));
|
||||||
///
|
///
|
||||||
/// let add = add.with_overload(|a: f32, b: f32, c: f32| a + b + c);
|
/// let add = add.with_overload(|a: f32, b: f32, c: f32| a + b + c);
|
||||||
/// assert_eq!(add.arg_count(), 2..=3);
|
/// assert!(add.arg_count().contains(2));
|
||||||
|
/// assert!(add.arg_count().contains(3));
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [overloaded]: Self::with_overload
|
/// [overloaded]: Self::with_overload
|
||||||
pub fn arg_count(&self) -> RangeInclusive<usize> {
|
pub fn arg_count(&self) -> ArgCount {
|
||||||
self.internal.arg_count()
|
self.internal.arg_count()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -510,7 +512,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
error,
|
error,
|
||||||
FunctionError::ArgCountMismatch {
|
FunctionError::ArgCountMismatch {
|
||||||
expected: 2..=2,
|
expected: ArgCount::new(2).unwrap(),
|
||||||
received: 1
|
received: 1
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -527,12 +529,16 @@ mod tests {
|
|||||||
.push_owned(2_i32)
|
.push_owned(2_i32)
|
||||||
.push_owned(3_i32)
|
.push_owned(3_i32)
|
||||||
.push_owned(4_i32);
|
.push_owned(4_i32);
|
||||||
|
|
||||||
let error = func.call(args).unwrap_err();
|
let error = func.call(args).unwrap_err();
|
||||||
|
|
||||||
|
let mut expected_count = ArgCount::new(2).unwrap();
|
||||||
|
expected_count.add(3);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
error,
|
error,
|
||||||
FunctionError::ArgCountMismatch {
|
FunctionError::ArgCountMismatch {
|
||||||
expected: 2..=3,
|
expected: expected_count,
|
||||||
received: 4
|
received: 4
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
|
use crate::func::args::ArgCount;
|
||||||
use crate::func::signature::{ArgListSignature, ArgumentSignature};
|
use crate::func::signature::{ArgListSignature, ArgumentSignature};
|
||||||
use crate::func::{ArgList, FunctionError, FunctionInfo, FunctionOverloadError};
|
use crate::func::{ArgList, FunctionError, FunctionInfo, FunctionOverloadError};
|
||||||
use alloc::borrow::Cow;
|
use alloc::borrow::Cow;
|
||||||
use bevy_utils::hashbrown::HashMap;
|
use bevy_utils::hashbrown::HashMap;
|
||||||
use core::fmt::{Debug, Formatter};
|
use core::fmt::{Debug, Formatter};
|
||||||
use core::ops::RangeInclusive;
|
|
||||||
|
|
||||||
/// An internal structure for storing a function and its corresponding [function information].
|
/// An internal structure for storing a function and its corresponding [function information].
|
||||||
///
|
///
|
||||||
@ -101,11 +101,9 @@ impl<F> DynamicFunctionInternal<F> {
|
|||||||
|
|
||||||
/// Returns the number of arguments the function expects.
|
/// Returns the number of arguments the function expects.
|
||||||
///
|
///
|
||||||
/// For[overloaded functions that can have a variable number of arguments,
|
/// For overloaded functions that can have a variable number of arguments,
|
||||||
/// this will return the minimum and maximum number of arguments.
|
/// this will contain the full set of counts for all signatures.
|
||||||
///
|
pub fn arg_count(&self) -> ArgCount {
|
||||||
/// Otherwise, the range will have the same start and end.
|
|
||||||
pub fn arg_count(&self) -> RangeInclusive<usize> {
|
|
||||||
self.info.arg_count()
|
self.info.arg_count()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,7 +115,7 @@ impl<F> DynamicFunctionInternal<F> {
|
|||||||
let expected_arg_count = self.arg_count();
|
let expected_arg_count = self.arg_count();
|
||||||
let received_arg_count = args.len();
|
let received_arg_count = args.len();
|
||||||
|
|
||||||
if !expected_arg_count.contains(&received_arg_count) {
|
if !expected_arg_count.contains(received_arg_count) {
|
||||||
Err(FunctionError::ArgCountMismatch {
|
Err(FunctionError::ArgCountMismatch {
|
||||||
expected: expected_arg_count,
|
expected: expected_arg_count,
|
||||||
received: received_arg_count,
|
received: received_arg_count,
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
use alloc::{borrow::Cow, boxed::Box, sync::Arc};
|
use alloc::{borrow::Cow, boxed::Box, sync::Arc};
|
||||||
use core::fmt::{Debug, Formatter};
|
use core::fmt::{Debug, Formatter};
|
||||||
use core::ops::RangeInclusive;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
use alloc::{boxed::Box, format, vec};
|
use alloc::{boxed::Box, format, vec};
|
||||||
|
|
||||||
use crate::func::{
|
use crate::func::{
|
||||||
args::ArgList, dynamic_function_internal::DynamicFunctionInternal, DynamicFunction,
|
args::{ArgCount, ArgList},
|
||||||
FunctionInfo, FunctionOverloadError, FunctionResult, IntoFunctionMut,
|
dynamic_function_internal::DynamicFunctionInternal,
|
||||||
|
DynamicFunction, FunctionInfo, FunctionOverloadError, FunctionResult, IntoFunctionMut,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A [`Box`] containing a callback to a reflected function.
|
/// A [`Box`] containing a callback to a reflected function.
|
||||||
@ -85,7 +85,10 @@ impl<'env> DynamicFunctionMut<'env> {
|
|||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics if no [`SignatureInfo`] is provided or if the conversion to [`FunctionInfo`] fails.
|
/// This function may panic for any of the following reasons:
|
||||||
|
/// - No [`SignatureInfo`] is provided.
|
||||||
|
/// - A provided [`SignatureInfo`] has more arguments than [`ArgCount::MAX_COUNT`].
|
||||||
|
/// - The conversion to [`FunctionInfo`] fails.
|
||||||
///
|
///
|
||||||
/// [calling]: crate::func::dynamic_function_mut::DynamicFunctionMut::call
|
/// [calling]: crate::func::dynamic_function_mut::DynamicFunctionMut::call
|
||||||
/// [`SignatureInfo`]: crate::func::SignatureInfo
|
/// [`SignatureInfo`]: crate::func::SignatureInfo
|
||||||
@ -313,23 +316,22 @@ impl<'env> DynamicFunctionMut<'env> {
|
|||||||
/// Returns the number of arguments the function expects.
|
/// Returns the number of arguments the function expects.
|
||||||
///
|
///
|
||||||
/// For [overloaded] functions that can have a variable number of arguments,
|
/// For [overloaded] functions that can have a variable number of arguments,
|
||||||
/// this will return the minimum and maximum number of arguments.
|
/// this will contain the full set of counts for all signatures.
|
||||||
///
|
|
||||||
/// Otherwise, the range will have the same start and end.
|
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use bevy_reflect::func::IntoFunctionMut;
|
/// # use bevy_reflect::func::IntoFunctionMut;
|
||||||
/// let add = (|a: i32, b: i32| a + b).into_function_mut();
|
/// let add = (|a: i32, b: i32| a + b).into_function_mut();
|
||||||
/// assert_eq!(add.arg_count(), 2..=2);
|
/// assert!(add.arg_count().contains(2));
|
||||||
///
|
///
|
||||||
/// let add = add.with_overload(|a: f32, b: f32, c: f32| a + b + c);
|
/// let add = add.with_overload(|a: f32, b: f32, c: f32| a + b + c);
|
||||||
/// assert_eq!(add.arg_count(), 2..=3);
|
/// assert!(add.arg_count().contains(2));
|
||||||
|
/// assert!(add.arg_count().contains(3));
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [overloaded]: Self::with_overload
|
/// [overloaded]: Self::with_overload
|
||||||
pub fn arg_count(&self) -> RangeInclusive<usize> {
|
pub fn arg_count(&self) -> ArgCount {
|
||||||
self.internal.arg_count()
|
self.internal.arg_count()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -412,7 +414,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
error,
|
error,
|
||||||
FunctionError::ArgCountMismatch {
|
FunctionError::ArgCountMismatch {
|
||||||
expected: 2..=2,
|
expected: ArgCount::new(2).unwrap(),
|
||||||
received: 1
|
received: 1
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -422,7 +424,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
error,
|
error,
|
||||||
FunctionError::ArgCountMismatch {
|
FunctionError::ArgCountMismatch {
|
||||||
expected: 2..=2,
|
expected: ArgCount::new(2).unwrap(),
|
||||||
received: 1
|
received: 1
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
use crate::func::signature::ArgumentSignature;
|
use crate::func::signature::ArgumentSignature;
|
||||||
use crate::func::{args::ArgError, Return};
|
use crate::func::{
|
||||||
|
args::{ArgCount, ArgError},
|
||||||
|
Return,
|
||||||
|
};
|
||||||
use alloc::borrow::Cow;
|
use alloc::borrow::Cow;
|
||||||
use bevy_utils::HashSet;
|
use bevy_utils::HashSet;
|
||||||
use core::ops::RangeInclusive;
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
@ -18,11 +20,8 @@ pub enum FunctionError {
|
|||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
ArgError(#[from] ArgError),
|
ArgError(#[from] ArgError),
|
||||||
/// The number of arguments provided does not match the expected number.
|
/// The number of arguments provided does not match the expected number.
|
||||||
#[error("expected {expected:?} arguments but received {received}")]
|
#[error("received {received} arguments but expected one of {expected:?}")]
|
||||||
ArgCountMismatch {
|
ArgCountMismatch { expected: ArgCount, received: usize },
|
||||||
expected: RangeInclusive<usize>,
|
|
||||||
received: usize,
|
|
||||||
},
|
|
||||||
/// No overload was found for the given set of arguments.
|
/// No overload was found for the given set of arguments.
|
||||||
#[error("no overload found for arguments with signature `{received:?}`, expected one of `{expected:?}`")]
|
#[error("no overload found for arguments with signature `{received:?}`, expected one of `{expected:?}`")]
|
||||||
NoOverload {
|
NoOverload {
|
||||||
@ -51,6 +50,12 @@ pub enum FunctionOverloadError {
|
|||||||
/// An error that occurs when attempting to add a function overload with a duplicate signature.
|
/// An error that occurs when attempting to add a function overload with a duplicate signature.
|
||||||
#[error("could not add function overload: duplicate found for signature `{0:?}`")]
|
#[error("could not add function overload: duplicate found for signature `{0:?}`")]
|
||||||
DuplicateSignature(ArgumentSignature),
|
DuplicateSignature(ArgumentSignature),
|
||||||
|
#[error(
|
||||||
|
"argument signature `{:?}` has too many arguments (max {})",
|
||||||
|
0,
|
||||||
|
ArgCount::MAX_COUNT
|
||||||
|
)]
|
||||||
|
TooManyArguments(ArgumentSignature),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An error that occurs when registering a function into a [`FunctionRegistry`].
|
/// An error that occurs when registering a function into a [`FunctionRegistry`].
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
func::{ArgList, DynamicFunction, FunctionInfo, FunctionResult},
|
func::{
|
||||||
|
args::{ArgCount, ArgList},
|
||||||
|
DynamicFunction, FunctionInfo, FunctionResult,
|
||||||
|
},
|
||||||
PartialReflect,
|
PartialReflect,
|
||||||
};
|
};
|
||||||
use alloc::borrow::Cow;
|
use alloc::borrow::Cow;
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use core::ops::RangeInclusive;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
use alloc::{boxed::Box, format, vec};
|
use alloc::{boxed::Box, format, vec};
|
||||||
@ -51,10 +53,8 @@ pub trait Function: PartialReflect + Debug {
|
|||||||
/// Returns the number of arguments the function expects.
|
/// Returns the number of arguments the function expects.
|
||||||
///
|
///
|
||||||
/// For overloaded functions that can have a variable number of arguments,
|
/// For overloaded functions that can have a variable number of arguments,
|
||||||
/// this will return the minimum and maximum number of arguments.
|
/// this will contain the full set of counts for all signatures.
|
||||||
///
|
fn arg_count(&self) -> ArgCount {
|
||||||
/// Otherwise, the range will have the same start and end.
|
|
||||||
fn arg_count(&self) -> RangeInclusive<usize> {
|
|
||||||
self.info().arg_count()
|
self.info().arg_count()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
use alloc::{borrow::Cow, vec};
|
use alloc::{borrow::Cow, vec};
|
||||||
|
use core::fmt::{Debug, Formatter};
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
use alloc::{boxed::Box, format, vec};
|
use alloc::{boxed::Box, format, vec};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
func::args::{ArgInfo, GetOwnership, Ownership},
|
func::args::{ArgCount, ArgCountOutOfBoundsError, ArgInfo, GetOwnership, Ownership},
|
||||||
func::signature::ArgumentSignature,
|
func::signature::ArgumentSignature,
|
||||||
func::FunctionOverloadError,
|
func::FunctionOverloadError,
|
||||||
type_info::impl_type_methods,
|
type_info::impl_type_methods,
|
||||||
Type, TypePath,
|
Type, TypePath,
|
||||||
};
|
};
|
||||||
|
|
||||||
use core::fmt::{Debug, Formatter};
|
|
||||||
use core::ops::RangeInclusive;
|
|
||||||
use variadics_please::all_tuples;
|
use variadics_please::all_tuples;
|
||||||
|
|
||||||
/// Type information for a [`DynamicFunction`] or [`DynamicFunctionMut`].
|
/// Type information for a [`DynamicFunction`] or [`DynamicFunctionMut`].
|
||||||
@ -28,14 +27,21 @@ use variadics_please::all_tuples;
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct FunctionInfo {
|
pub struct FunctionInfo {
|
||||||
name: Option<Cow<'static, str>>,
|
name: Option<Cow<'static, str>>,
|
||||||
|
arg_count: ArgCount,
|
||||||
signatures: Box<[SignatureInfo]>,
|
signatures: Box<[SignatureInfo]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FunctionInfo {
|
impl FunctionInfo {
|
||||||
/// Create a new [`FunctionInfo`] for a function with the given signature.
|
/// Create a new [`FunctionInfo`] for a function with the given signature.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the given signature has more than the maximum number of arguments
|
||||||
|
/// as specified by [`ArgCount::MAX_COUNT`].
|
||||||
pub fn new(signature: SignatureInfo) -> Self {
|
pub fn new(signature: SignatureInfo) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: signature.name.clone(),
|
name: signature.name.clone(),
|
||||||
|
arg_count: ArgCount::new(signature.arg_count()).unwrap(),
|
||||||
signatures: vec![signature].into(),
|
signatures: vec![signature].into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -48,9 +54,23 @@ impl FunctionInfo {
|
|||||||
) -> Result<Self, FunctionOverloadError> {
|
) -> Result<Self, FunctionOverloadError> {
|
||||||
let mut iter = signatures.into_iter();
|
let mut iter = signatures.into_iter();
|
||||||
|
|
||||||
let mut info = Self::new(iter.next().ok_or(FunctionOverloadError::MissingSignature)?);
|
let base = iter.next().ok_or(FunctionOverloadError::MissingSignature)?;
|
||||||
|
|
||||||
|
if base.arg_count() > ArgCount::MAX_COUNT {
|
||||||
|
return Err(FunctionOverloadError::TooManyArguments(
|
||||||
|
ArgumentSignature::from(&base),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut info = Self::new(base);
|
||||||
|
|
||||||
for signature in iter {
|
for signature in iter {
|
||||||
|
if signature.arg_count() > ArgCount::MAX_COUNT {
|
||||||
|
return Err(FunctionOverloadError::TooManyArguments(
|
||||||
|
ArgumentSignature::from(&signature),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
info = info.with_overload(signature).map_err(|sig| {
|
info = info.with_overload(signature).map_err(|sig| {
|
||||||
FunctionOverloadError::DuplicateSignature(ArgumentSignature::from(&sig))
|
FunctionOverloadError::DuplicateSignature(ArgumentSignature::from(&sig))
|
||||||
})?;
|
})?;
|
||||||
@ -102,6 +122,11 @@ impl FunctionInfo {
|
|||||||
///
|
///
|
||||||
/// If a signature with the same [`ArgumentSignature`] already exists,
|
/// If a signature with the same [`ArgumentSignature`] already exists,
|
||||||
/// an error is returned with the given signature.
|
/// an error is returned with the given signature.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the given signature has more than the maximum number of arguments
|
||||||
|
/// as specified by [`ArgCount::MAX_COUNT`].
|
||||||
pub fn with_overload(mut self, signature: SignatureInfo) -> Result<Self, SignatureInfo> {
|
pub fn with_overload(mut self, signature: SignatureInfo) -> Result<Self, SignatureInfo> {
|
||||||
let is_duplicate = self.signatures.iter().any(|s| {
|
let is_duplicate = self.signatures.iter().any(|s| {
|
||||||
s.arg_count() == signature.arg_count()
|
s.arg_count() == signature.arg_count()
|
||||||
@ -112,6 +137,7 @@ impl FunctionInfo {
|
|||||||
return Err(signature);
|
return Err(signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.arg_count.add(signature.arg_count());
|
||||||
self.signatures = IntoIterator::into_iter(self.signatures)
|
self.signatures = IntoIterator::into_iter(self.signatures)
|
||||||
.chain(Some(signature))
|
.chain(Some(signature))
|
||||||
.collect();
|
.collect();
|
||||||
@ -121,16 +147,9 @@ impl FunctionInfo {
|
|||||||
/// Returns the number of arguments the function expects.
|
/// Returns the number of arguments the function expects.
|
||||||
///
|
///
|
||||||
/// For overloaded functions that can have a variable number of arguments,
|
/// For overloaded functions that can have a variable number of arguments,
|
||||||
/// this will return the minimum and maximum number of arguments.
|
/// this will contain the full set of counts for all signatures.
|
||||||
///
|
pub fn arg_count(&self) -> ArgCount {
|
||||||
/// Otherwise, the range will have the same start and end.
|
self.arg_count
|
||||||
pub fn arg_count(&self) -> RangeInclusive<usize> {
|
|
||||||
self.signatures
|
|
||||||
.iter()
|
|
||||||
.map(SignatureInfo::arg_count)
|
|
||||||
.fold(RangeInclusive::new(usize::MAX, usize::MIN), |acc, count| {
|
|
||||||
RangeInclusive::new((*acc.start()).min(count), (*acc.end()).max(count))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The signatures of the function.
|
/// The signatures of the function.
|
||||||
@ -164,6 +183,11 @@ impl FunctionInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Extend this [`FunctionInfo`] with another without checking for duplicates.
|
/// Extend this [`FunctionInfo`] with another without checking for duplicates.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the given signature has more than the maximum number of arguments
|
||||||
|
/// as specified by [`ArgCount::MAX_COUNT`].
|
||||||
pub(super) fn extend_unchecked(&mut self, other: FunctionInfo) {
|
pub(super) fn extend_unchecked(&mut self, other: FunctionInfo) {
|
||||||
if self.name.is_none() {
|
if self.name.is_none() {
|
||||||
self.name = other.name;
|
self.name = other.name;
|
||||||
@ -173,12 +197,26 @@ impl FunctionInfo {
|
|||||||
self.signatures = IntoIterator::into_iter(signatures)
|
self.signatures = IntoIterator::into_iter(signatures)
|
||||||
.chain(IntoIterator::into_iter(other.signatures))
|
.chain(IntoIterator::into_iter(other.signatures))
|
||||||
.collect();
|
.collect();
|
||||||
|
self.arg_count = self
|
||||||
|
.signatures
|
||||||
|
.iter()
|
||||||
|
.fold(ArgCount::default(), |mut count, sig| {
|
||||||
|
count.add(sig.arg_count());
|
||||||
|
count
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<SignatureInfo> for FunctionInfo {
|
impl TryFrom<SignatureInfo> for FunctionInfo {
|
||||||
fn from(info: SignatureInfo) -> Self {
|
type Error = ArgCountOutOfBoundsError;
|
||||||
Self::new(info)
|
|
||||||
|
fn try_from(signature: SignatureInfo) -> Result<Self, Self::Error> {
|
||||||
|
let count = signature.arg_count();
|
||||||
|
if count > ArgCount::MAX_COUNT {
|
||||||
|
return Err(ArgCountOutOfBoundsError(count));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self::new(signature))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -531,7 +569,7 @@ impl<'a> Debug for PrettyPrintSignatureInfo<'a> {
|
|||||||
///
|
///
|
||||||
/// let info = print.get_function_info();
|
/// let info = print.get_function_info();
|
||||||
/// assert!(info.name().unwrap().ends_with("print"));
|
/// assert!(info.name().unwrap().ends_with("print"));
|
||||||
/// assert!(info.arg_count().contains(&1));
|
/// assert!(info.arg_count().contains(1));
|
||||||
/// assert_eq!(info.base().args()[0].type_path(), "alloc::string::String");
|
/// assert_eq!(info.base().args()[0].type_path(), "alloc::string::String");
|
||||||
/// assert_eq!(info.base().return_info().type_path(), "()");
|
/// assert_eq!(info.base().return_info().type_path(), "()");
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -191,13 +191,13 @@ pub mod signature;
|
|||||||
mod tests {
|
mod tests {
|
||||||
use alloc::borrow::Cow;
|
use alloc::borrow::Cow;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use crate::func::args::ArgCount;
|
||||||
use crate::{
|
use crate::{
|
||||||
func::args::{ArgError, ArgList, Ownership},
|
func::args::{ArgError, ArgList, Ownership},
|
||||||
TypePath,
|
TypePath,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_error_on_missing_args() {
|
fn should_error_on_missing_args() {
|
||||||
fn foo(_: i32) {}
|
fn foo(_: i32) {}
|
||||||
@ -208,7 +208,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
result.unwrap_err(),
|
result.unwrap_err(),
|
||||||
FunctionError::ArgCountMismatch {
|
FunctionError::ArgCountMismatch {
|
||||||
expected: 1..=1,
|
expected: ArgCount::new(1).unwrap(),
|
||||||
received: 0
|
received: 0
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -224,7 +224,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
result.unwrap_err(),
|
result.unwrap_err(),
|
||||||
FunctionError::ArgCountMismatch {
|
FunctionError::ArgCountMismatch {
|
||||||
expected: 0..=0,
|
expected: ArgCount::new(0).unwrap(),
|
||||||
received: 1
|
received: 1
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -5,8 +5,9 @@ use alloc::{boxed::Box, format, vec};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
func::{
|
func::{
|
||||||
args::FromArg, macros::count_tokens, ArgList, FunctionError, FunctionResult, IntoReturn,
|
args::{ArgCount, FromArg},
|
||||||
ReflectFnMut,
|
macros::count_tokens,
|
||||||
|
ArgList, FunctionError, FunctionResult, IntoReturn, ReflectFnMut,
|
||||||
},
|
},
|
||||||
Reflect, TypePath,
|
Reflect, TypePath,
|
||||||
};
|
};
|
||||||
@ -96,7 +97,7 @@ macro_rules! impl_reflect_fn {
|
|||||||
|
|
||||||
if args.len() != COUNT {
|
if args.len() != COUNT {
|
||||||
return Err(FunctionError::ArgCountMismatch {
|
return Err(FunctionError::ArgCountMismatch {
|
||||||
expected: COUNT..=COUNT,
|
expected: ArgCount::new(COUNT).unwrap(),
|
||||||
received: args.len(),
|
received: args.len(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -125,7 +126,7 @@ macro_rules! impl_reflect_fn {
|
|||||||
|
|
||||||
if args.len() != COUNT {
|
if args.len() != COUNT {
|
||||||
return Err(FunctionError::ArgCountMismatch {
|
return Err(FunctionError::ArgCountMismatch {
|
||||||
expected: COUNT..=COUNT,
|
expected: ArgCount::new(COUNT).unwrap(),
|
||||||
received: args.len(),
|
received: args.len(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -155,7 +156,7 @@ macro_rules! impl_reflect_fn {
|
|||||||
|
|
||||||
if args.len() != COUNT {
|
if args.len() != COUNT {
|
||||||
return Err(FunctionError::ArgCountMismatch {
|
return Err(FunctionError::ArgCountMismatch {
|
||||||
expected: COUNT..=COUNT,
|
expected: ArgCount::new(COUNT).unwrap(),
|
||||||
received: args.len(),
|
received: args.len(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -185,7 +186,7 @@ macro_rules! impl_reflect_fn {
|
|||||||
|
|
||||||
if args.len() != COUNT {
|
if args.len() != COUNT {
|
||||||
return Err(FunctionError::ArgCountMismatch {
|
return Err(FunctionError::ArgCountMismatch {
|
||||||
expected: COUNT..=COUNT,
|
expected: ArgCount::new(COUNT).unwrap(),
|
||||||
received: args.len(),
|
received: args.len(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,9 @@ use alloc::{boxed::Box, format, vec};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
func::{
|
func::{
|
||||||
args::FromArg, macros::count_tokens, ArgList, FunctionError, FunctionResult, IntoReturn,
|
args::{ArgCount, FromArg},
|
||||||
|
macros::count_tokens,
|
||||||
|
ArgList, FunctionError, FunctionResult, IntoReturn,
|
||||||
},
|
},
|
||||||
Reflect, TypePath,
|
Reflect, TypePath,
|
||||||
};
|
};
|
||||||
@ -102,7 +104,7 @@ macro_rules! impl_reflect_fn_mut {
|
|||||||
|
|
||||||
if args.len() != COUNT {
|
if args.len() != COUNT {
|
||||||
return Err(FunctionError::ArgCountMismatch {
|
return Err(FunctionError::ArgCountMismatch {
|
||||||
expected: COUNT..=COUNT,
|
expected: ArgCount::new(COUNT).unwrap(),
|
||||||
received: args.len(),
|
received: args.len(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -131,7 +133,7 @@ macro_rules! impl_reflect_fn_mut {
|
|||||||
|
|
||||||
if args.len() != COUNT {
|
if args.len() != COUNT {
|
||||||
return Err(FunctionError::ArgCountMismatch {
|
return Err(FunctionError::ArgCountMismatch {
|
||||||
expected: COUNT..=COUNT,
|
expected: ArgCount::new(COUNT).unwrap(),
|
||||||
received: args.len(),
|
received: args.len(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -161,7 +163,7 @@ macro_rules! impl_reflect_fn_mut {
|
|||||||
|
|
||||||
if args.len() != COUNT {
|
if args.len() != COUNT {
|
||||||
return Err(FunctionError::ArgCountMismatch {
|
return Err(FunctionError::ArgCountMismatch {
|
||||||
expected: COUNT..=COUNT,
|
expected: ArgCount::new(COUNT).unwrap(),
|
||||||
received: args.len(),
|
received: args.len(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -191,7 +193,7 @@ macro_rules! impl_reflect_fn_mut {
|
|||||||
|
|
||||||
if args.len() != COUNT {
|
if args.len() != COUNT {
|
||||||
return Err(FunctionError::ArgCountMismatch {
|
return Err(FunctionError::ArgCountMismatch {
|
||||||
expected: COUNT..=COUNT,
|
expected: ArgCount::new(COUNT).unwrap(),
|
||||||
received: args.len(),
|
received: args.len(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user