From f93aadd0dddba6e34222f2596a33492153f723db Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sat, 7 Dec 2024 17:34:11 -0700 Subject: [PATCH] Small optimization for ArgumentSignature from ArgList --- .../src/func/dynamic_function_internal.rs | 10 +-- crates/bevy_reflect/src/func/signature.rs | 74 ++++++++++++++++++- 2 files changed, 78 insertions(+), 6 deletions(-) diff --git a/crates/bevy_reflect/src/func/dynamic_function_internal.rs b/crates/bevy_reflect/src/func/dynamic_function_internal.rs index c057b8c5df..30d89e2236 100644 --- a/crates/bevy_reflect/src/func/dynamic_function_internal.rs +++ b/crates/bevy_reflect/src/func/dynamic_function_internal.rs @@ -1,4 +1,4 @@ -use crate::func::signature::ArgumentSignature; +use crate::func::signature::{ArgListSignature, ArgumentSignature}; use crate::func::{ArgList, FunctionError, FunctionInfo, FunctionOverloadError}; use alloc::borrow::Cow; use bevy_utils::hashbrown::HashMap; @@ -62,13 +62,13 @@ impl DynamicFunctionInternal { return Ok(&self.functions[0]); } - let signature = ArgumentSignature::from(args); + let signature = ArgListSignature::from(args); self.arg_map .get(&signature) .map(|index| &self.functions[*index]) .ok_or_else(|| FunctionError::NoOverload { expected: self.arg_map.keys().cloned().collect(), - received: signature, + received: ArgumentSignature::from(args), }) } @@ -83,13 +83,13 @@ impl DynamicFunctionInternal { return Ok(&mut self.functions[0]); } - let signature = ArgumentSignature::from(args); + let signature = ArgListSignature::from(args); self.arg_map .get(&signature) .map(|index| &mut self.functions[*index]) .ok_or_else(|| FunctionError::NoOverload { expected: self.arg_map.keys().cloned().collect(), - received: signature, + received: ArgumentSignature::from(args), }) } diff --git a/crates/bevy_reflect/src/func/signature.rs b/crates/bevy_reflect/src/func/signature.rs index abda0eaa98..965ff401e0 100644 --- a/crates/bevy_reflect/src/func/signature.rs +++ b/crates/bevy_reflect/src/func/signature.rs @@ -14,8 +14,10 @@ use crate::func::args::ArgInfo; use crate::func::{ArgList, SignatureInfo}; use crate::Type; +use bevy_utils::hashbrown::Equivalent; use core::borrow::Borrow; use core::fmt::{Debug, Formatter}; +use core::hash::{Hash, Hasher}; use core::ops::{Deref, DerefMut}; /// The signature of a function. @@ -57,13 +59,69 @@ impl> From for Signature { } } +/// A wrapper around a borrowed [`ArgList`] that can be used as an +/// [equivalent] of an [`ArgumentSignature`]. +/// +/// [equivalent]: Equivalent +pub(super) struct ArgListSignature<'a, 'b>(&'a ArgList<'b>); + +impl Equivalent for ArgListSignature<'_, '_> { + fn equivalent(&self, key: &ArgumentSignature) -> bool { + self.len() == key.len() && self.iter().eq(key.iter()) + } +} + +impl<'a, 'b> ArgListSignature<'a, 'b> { + pub fn iter(&self) -> impl ExactSizeIterator { + self.0.iter().map(|arg| { + arg.value() + .get_represented_type_info() + .unwrap_or_else(|| { + panic!("no `TypeInfo` found for argument: {:?}", arg); + }) + .ty() + }) + } + + pub fn len(&self) -> usize { + self.0.len() + } +} + +impl Eq for ArgListSignature<'_, '_> {} +impl PartialEq for ArgListSignature<'_, '_> { + fn eq(&self, other: &Self) -> bool { + self.len() == other.len() && self.iter().eq(other.iter()) + } +} + +impl Hash for ArgListSignature<'_, '_> { + fn hash(&self, state: &mut H) { + self.0.iter().for_each(|arg| { + arg.value() + .get_represented_type_info() + .unwrap_or_else(|| { + panic!("no `TypeInfo` found for argument: {:?}", arg); + }) + .ty() + .hash(state); + }); + } +} + +impl<'a, 'b> From<&'a ArgList<'b>> for ArgListSignature<'a, 'b> { + fn from(args: &'a ArgList<'b>) -> Self { + Self(args) + } +} + /// The argument-portion of a function signature. /// /// For example, given a function signature `(a: i32, b: f32) -> u32`, /// the argument signature would be `(i32, f32)`. /// /// This can be used as a way to compare or hash functions based on their arguments. -#[derive(Clone, PartialEq, Eq, Hash)] +#[derive(Clone)] pub struct ArgumentSignature(Box<[Type]>); impl Debug for ArgumentSignature { @@ -90,6 +148,20 @@ impl DerefMut for ArgumentSignature { } } +impl Eq for ArgumentSignature {} + +impl PartialEq for ArgumentSignature { + fn eq(&self, other: &Self) -> bool { + self.0.len() == other.0.len() && self.0.iter().eq(other.0.iter()) + } +} + +impl Hash for ArgumentSignature { + fn hash(&self, state: &mut H) { + self.0.iter().for_each(|ty| ty.hash(state)); + } +} + impl FromIterator for ArgumentSignature { fn from_iter>(iter: T) -> Self { Self(iter.into_iter().collect())