mirror of
https://github.com/bevyengine/bevy
synced 2024-12-21 10:33:08 +00:00
Added non-panicking method for adding overloads
This commit is contained in:
parent
38b3cbf5c5
commit
77ae7cf822
3 changed files with 93 additions and 27 deletions
|
@ -3,8 +3,8 @@ use crate::{
|
||||||
__macro_exports::RegisterForReflection,
|
__macro_exports::RegisterForReflection,
|
||||||
func::{
|
func::{
|
||||||
args::ArgList, function_map::FunctionMap, info::FunctionInfoType,
|
args::ArgList, function_map::FunctionMap, info::FunctionInfoType,
|
||||||
signature::ArgumentSignature, DynamicFunctionMut, Function, FunctionError, FunctionResult,
|
signature::ArgumentSignature, DynamicFunctionMut, Function, FunctionError,
|
||||||
IntoFunction, IntoFunctionMut,
|
FunctionOverloadError, FunctionResult, IntoFunction, IntoFunctionMut,
|
||||||
},
|
},
|
||||||
serde::Serializable,
|
serde::Serializable,
|
||||||
ApplyError, MaybeTyped, PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned,
|
ApplyError, MaybeTyped, PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned,
|
||||||
|
@ -150,6 +150,8 @@ impl<'env> DynamicFunction<'env> {
|
||||||
///
|
///
|
||||||
/// Panics if the function, `F`, contains a signature already found in this function.
|
/// Panics if the function, `F`, contains a signature already found in this function.
|
||||||
///
|
///
|
||||||
|
/// For a non-panicking version, see [`try_with_overload`].
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -227,6 +229,7 @@ impl<'env> DynamicFunction<'env> {
|
||||||
///
|
///
|
||||||
/// [argument signature]: ArgumentSignature
|
/// [argument signature]: ArgumentSignature
|
||||||
/// [name]: Self::name
|
/// [name]: Self::name
|
||||||
|
/// [`try_with_overload`]: Self::try_with_overload
|
||||||
pub fn with_overload<'a, F: IntoFunction<'a, Marker>, Marker>(
|
pub fn with_overload<'a, F: IntoFunction<'a, Marker>, Marker>(
|
||||||
self,
|
self,
|
||||||
function: F,
|
function: F,
|
||||||
|
@ -237,16 +240,44 @@ impl<'env> DynamicFunction<'env> {
|
||||||
let function = function.into_function();
|
let function = function.into_function();
|
||||||
|
|
||||||
let name = self.name.clone();
|
let name = self.name.clone();
|
||||||
let mut function_map = self.function_map;
|
let function_map = self
|
||||||
function_map
|
.function_map
|
||||||
.merge(function.function_map)
|
.merge(function.function_map)
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|(_, err)| {
|
||||||
panic!("{}", err);
|
panic!("{}", err);
|
||||||
});
|
});
|
||||||
|
|
||||||
DynamicFunction { name, function_map }
|
DynamicFunction { name, function_map }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Attempt to add an overload to this function.
|
||||||
|
///
|
||||||
|
/// If the function, `F`, contains a signature already found in this function,
|
||||||
|
/// an error will be returned along with the original function.
|
||||||
|
///
|
||||||
|
/// For a panicking version, see [`with_overload`].
|
||||||
|
///
|
||||||
|
/// [`with_overload`]: Self::with_overload
|
||||||
|
pub fn try_with_overload<F: IntoFunction<'env, Marker>, Marker>(
|
||||||
|
self,
|
||||||
|
function: F,
|
||||||
|
) -> Result<Self, (Box<Self>, FunctionOverloadError)> {
|
||||||
|
let function = function.into_function();
|
||||||
|
|
||||||
|
let name = self.name.clone();
|
||||||
|
|
||||||
|
match self.function_map.merge(function.function_map) {
|
||||||
|
Ok(function_map) => Ok(Self { name, function_map }),
|
||||||
|
Err((function_map, err)) => Err((
|
||||||
|
Box::new(Self {
|
||||||
|
name,
|
||||||
|
function_map: *function_map,
|
||||||
|
}),
|
||||||
|
err,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Call the function with the given arguments.
|
/// Call the function with the given arguments.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
|
|
|
@ -6,7 +6,7 @@ use alloc::{boxed::Box, format, vec};
|
||||||
|
|
||||||
use crate::func::{
|
use crate::func::{
|
||||||
args::ArgList, function_map::FunctionMap, signature::ArgumentSignature, DynamicFunction,
|
args::ArgList, function_map::FunctionMap, signature::ArgumentSignature, DynamicFunction,
|
||||||
FunctionError, FunctionInfoType, FunctionResult, IntoFunctionMut,
|
FunctionError, FunctionInfoType, FunctionOverloadError, FunctionResult, IntoFunctionMut,
|
||||||
};
|
};
|
||||||
use bevy_utils::HashMap;
|
use bevy_utils::HashMap;
|
||||||
|
|
||||||
|
@ -158,6 +158,8 @@ impl<'env> DynamicFunctionMut<'env> {
|
||||||
///
|
///
|
||||||
/// Panics if the function, `F`, contains a signature already found in this function.
|
/// Panics if the function, `F`, contains a signature already found in this function.
|
||||||
///
|
///
|
||||||
|
/// For a non-panicking version, see [`try_with_overload`].
|
||||||
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -189,6 +191,7 @@ impl<'env> DynamicFunctionMut<'env> {
|
||||||
///
|
///
|
||||||
/// [argument signature]: ArgumentSignature
|
/// [argument signature]: ArgumentSignature
|
||||||
/// [name]: Self::name
|
/// [name]: Self::name
|
||||||
|
/// [`try_with_overload`]: Self::try_with_overload
|
||||||
pub fn with_overload<'a, F: IntoFunctionMut<'a, Marker>, Marker>(
|
pub fn with_overload<'a, F: IntoFunctionMut<'a, Marker>, Marker>(
|
||||||
self,
|
self,
|
||||||
function: F,
|
function: F,
|
||||||
|
@ -199,14 +202,44 @@ impl<'env> DynamicFunctionMut<'env> {
|
||||||
let function = function.into_function_mut();
|
let function = function.into_function_mut();
|
||||||
|
|
||||||
let name = self.name.clone();
|
let name = self.name.clone();
|
||||||
let mut function_map = self.function_map;
|
let function_map = self
|
||||||
function_map
|
.function_map
|
||||||
.merge(function.function_map)
|
.merge(function.function_map)
|
||||||
.unwrap_or_else(|_| todo!());
|
.unwrap_or_else(|(_, err)| {
|
||||||
|
panic!("{}", err);
|
||||||
|
});
|
||||||
|
|
||||||
DynamicFunctionMut { name, function_map }
|
DynamicFunctionMut { name, function_map }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Attempt to add an overload to this function.
|
||||||
|
///
|
||||||
|
/// If the function, `F`, contains a signature already found in this function,
|
||||||
|
/// an error will be returned along with the original function.
|
||||||
|
///
|
||||||
|
/// For a panicking version, see [`with_overload`].
|
||||||
|
///
|
||||||
|
/// [`with_overload`]: Self::with_overload
|
||||||
|
pub fn try_with_overload<F: IntoFunctionMut<'env, Marker>, Marker>(
|
||||||
|
self,
|
||||||
|
function: F,
|
||||||
|
) -> Result<Self, (Box<Self>, FunctionOverloadError)> {
|
||||||
|
let function = function.into_function_mut();
|
||||||
|
|
||||||
|
let name = self.name.clone();
|
||||||
|
|
||||||
|
match self.function_map.merge(function.function_map) {
|
||||||
|
Ok(function_map) => Ok(Self { name, function_map }),
|
||||||
|
Err((function_map, err)) => Err((
|
||||||
|
Box::new(Self {
|
||||||
|
name,
|
||||||
|
function_map: *function_map,
|
||||||
|
}),
|
||||||
|
err,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Call the function with the given arguments.
|
/// Call the function with the given arguments.
|
||||||
///
|
///
|
||||||
/// Variables that are captured mutably by this function
|
/// Variables that are captured mutably by this function
|
||||||
|
|
|
@ -59,14 +59,14 @@ impl<F> FunctionMap<F> {
|
||||||
/// Merge another [`FunctionMap`] into this one.
|
/// Merge another [`FunctionMap`] into this one.
|
||||||
///
|
///
|
||||||
/// If the other map contains any functions with the same signature as this one,
|
/// If the other map contains any functions with the same signature as this one,
|
||||||
/// an error will be returned and the original map will remain unchanged.
|
/// an error will be returned along with the original, unchanged map.
|
||||||
pub fn merge(&mut self, other: Self) -> Result<(), FunctionOverloadError> {
|
pub fn merge(mut self, other: Self) -> Result<Self, (Box<Self>, FunctionOverloadError)> {
|
||||||
// === Function Map === //
|
// === Function Map === //
|
||||||
let mut other_indices = HashMap::new();
|
let mut other_indices = HashMap::new();
|
||||||
|
|
||||||
for (sig, index) in other.indices {
|
for (sig, index) in other.indices {
|
||||||
if self.indices.contains_key(&sig) {
|
if self.indices.contains_key(&sig) {
|
||||||
return Err(FunctionOverloadError { signature: sig });
|
return Err((Box::new(self), FunctionOverloadError { signature: sig }));
|
||||||
}
|
}
|
||||||
|
|
||||||
other_indices.insert(sig, self.functions.len() + index);
|
other_indices.insert(sig, self.functions.len() + index);
|
||||||
|
@ -78,7 +78,7 @@ impl<F> FunctionMap<F> {
|
||||||
for info in other.info.into_iter() {
|
for info in other.info.into_iter() {
|
||||||
let sig = ArgumentSignature::from(&info);
|
let sig = ArgumentSignature::from(&info);
|
||||||
if self.indices.contains_key(&sig) {
|
if self.indices.contains_key(&sig) {
|
||||||
return Err(FunctionOverloadError { signature: sig });
|
return Err((Box::new(self), FunctionOverloadError { signature: sig }));
|
||||||
}
|
}
|
||||||
other_infos.push(info);
|
other_infos.push(info);
|
||||||
}
|
}
|
||||||
|
@ -86,16 +86,16 @@ impl<F> FunctionMap<F> {
|
||||||
// === Update === //
|
// === Update === //
|
||||||
self.indices.extend(other_indices);
|
self.indices.extend(other_indices);
|
||||||
self.functions.extend(other.functions);
|
self.functions.extend(other.functions);
|
||||||
self.info = match &self.info {
|
self.info = match self.info {
|
||||||
FunctionInfoType::Standard(info) => FunctionInfoType::Overloaded(
|
FunctionInfoType::Standard(info) => {
|
||||||
std::iter::once(info.clone()).chain(other_infos).collect(),
|
FunctionInfoType::Overloaded(std::iter::once(info).chain(other_infos).collect())
|
||||||
),
|
|
||||||
FunctionInfoType::Overloaded(infos) => {
|
|
||||||
FunctionInfoType::Overloaded(infos.iter().cloned().chain(other_infos).collect())
|
|
||||||
}
|
}
|
||||||
|
FunctionInfoType::Overloaded(infos) => FunctionInfoType::Overloaded(
|
||||||
|
IntoIterator::into_iter(infos).chain(other_infos).collect(),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_merge_function_maps() {
|
fn should_merge_function_maps() {
|
||||||
let mut map_a = FunctionMap {
|
let map_a = FunctionMap {
|
||||||
info: FunctionInfoType::Overloaded(Box::new([
|
info: FunctionInfoType::Overloaded(Box::new([
|
||||||
FunctionInfo::anonymous().with_arg::<i8>("arg0"),
|
FunctionInfo::anonymous().with_arg::<i8>("arg0"),
|
||||||
FunctionInfo::anonymous().with_arg::<i16>("arg0"),
|
FunctionInfo::anonymous().with_arg::<i16>("arg0"),
|
||||||
|
@ -135,11 +135,11 @@ mod tests {
|
||||||
]),
|
]),
|
||||||
};
|
};
|
||||||
|
|
||||||
map_a.merge(map_b).unwrap();
|
let map = map_a.merge(map_b).unwrap();
|
||||||
|
|
||||||
assert_eq!(map_a.functions, vec!['a', 'b', 'c', 'd', 'e', 'f']);
|
assert_eq!(map.functions, vec!['a', 'b', 'c', 'd', 'e', 'f']);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
map_a.indices,
|
map.indices,
|
||||||
HashMap::from([
|
HashMap::from([
|
||||||
(ArgumentSignature::from_iter([Type::of::<i8>()]), 0),
|
(ArgumentSignature::from_iter([Type::of::<i8>()]), 0),
|
||||||
(ArgumentSignature::from_iter([Type::of::<i16>()]), 1),
|
(ArgumentSignature::from_iter([Type::of::<i16>()]), 1),
|
||||||
|
@ -153,7 +153,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_error_on_duplicate_signature() {
|
fn should_return_error_on_duplicate_signature() {
|
||||||
let mut map_a = FunctionMap {
|
let map_a = FunctionMap {
|
||||||
info: FunctionInfoType::Overloaded(Box::new([
|
info: FunctionInfoType::Overloaded(Box::new([
|
||||||
FunctionInfo::anonymous().with_arg::<i8>("arg0"),
|
FunctionInfo::anonymous().with_arg::<i8>("arg0"),
|
||||||
FunctionInfo::anonymous().with_arg::<i16>("arg0"),
|
FunctionInfo::anonymous().with_arg::<i16>("arg0"),
|
||||||
|
@ -181,9 +181,11 @@ mod tests {
|
||||||
]),
|
]),
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = map_a.merge(map_b);
|
let Err((map_a, error)) = map_a.merge(map_b) else {
|
||||||
|
panic!("expected an error");
|
||||||
|
};
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result.unwrap_err(),
|
error,
|
||||||
FunctionOverloadError {
|
FunctionOverloadError {
|
||||||
signature: ArgumentSignature::from_iter([Type::of::<i16>()])
|
signature: ArgumentSignature::from_iter([Type::of::<i16>()])
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue