mirror of
https://github.com/bevyengine/bevy
synced 2024-12-21 02:23:08 +00:00
Added Signature
and ArgumentSignature
types
This commit is contained in:
parent
85482b393a
commit
ba987ef60d
2 changed files with 143 additions and 0 deletions
|
@ -154,6 +154,7 @@ mod reflect_fn;
|
||||||
mod reflect_fn_mut;
|
mod reflect_fn_mut;
|
||||||
mod registry;
|
mod registry;
|
||||||
mod return_type;
|
mod return_type;
|
||||||
|
pub mod signature;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
142
crates/bevy_reflect/src/func/signature.rs
Normal file
142
crates/bevy_reflect/src/func/signature.rs
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
//! Function signature types.
|
||||||
|
//!
|
||||||
|
//! Function signatures differ from [`FunctionInfo`] in that they are only concerned
|
||||||
|
//! about the types and order of the arguments and return type of a function.
|
||||||
|
//!
|
||||||
|
//! The names of arguments do not matter,
|
||||||
|
//! nor does any other information about the function such as its name or other attributes.
|
||||||
|
//!
|
||||||
|
//! This makes signatures useful for comparing or hashing functions strictly based on their
|
||||||
|
//! arguments and return type.
|
||||||
|
|
||||||
|
use crate::func::args::ArgInfo;
|
||||||
|
use crate::func::FunctionInfo;
|
||||||
|
use crate::Type;
|
||||||
|
use core::borrow::Borrow;
|
||||||
|
use core::fmt::{Debug, Formatter};
|
||||||
|
use core::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
|
/// The signature of a function.
|
||||||
|
///
|
||||||
|
/// This can be used as a way to compare or hash functions based on their arguments and return type.
|
||||||
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct Signature {
|
||||||
|
args: ArgumentSignature,
|
||||||
|
ret: Type,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Signature {
|
||||||
|
/// Create a new function signature with the given argument signature and return type.
|
||||||
|
pub fn new(args: ArgumentSignature, ret: Type) -> Self {
|
||||||
|
Self { args, ret }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the argument signature of the function.
|
||||||
|
pub fn args(&self) -> &ArgumentSignature {
|
||||||
|
&self.args
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the return type of the function.
|
||||||
|
pub fn return_type(&self) -> &Type {
|
||||||
|
&self.ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for Signature {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||||
|
write!(f, "{:?} -> {:?}", self.args, self.ret)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Borrow<FunctionInfo>> From<T> for Signature {
|
||||||
|
fn from(info: T) -> Self {
|
||||||
|
let info = info.borrow();
|
||||||
|
Self::new(ArgumentSignature::from(info), *info.return_info().ty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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)]
|
||||||
|
pub struct ArgumentSignature(Box<[Type]>);
|
||||||
|
|
||||||
|
impl Debug for ArgumentSignature {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||||
|
let mut tuple = f.debug_tuple("");
|
||||||
|
for ty in self.0.iter() {
|
||||||
|
tuple.field(ty);
|
||||||
|
}
|
||||||
|
tuple.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for ArgumentSignature {
|
||||||
|
type Target = [Type];
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerefMut for ArgumentSignature {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromIterator<Type> for ArgumentSignature {
|
||||||
|
fn from_iter<T: IntoIterator<Item = Type>>(iter: T) -> Self {
|
||||||
|
Self(iter.into_iter().collect())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Borrow<FunctionInfo>> From<T> for ArgumentSignature {
|
||||||
|
fn from(info: T) -> Self {
|
||||||
|
Self(
|
||||||
|
info.borrow()
|
||||||
|
.args()
|
||||||
|
.iter()
|
||||||
|
.map(ArgInfo::ty)
|
||||||
|
.copied()
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::func::TypedFunction;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_generate_signature_from_function_info() {
|
||||||
|
fn add(a: i32, b: f32) -> u32 {
|
||||||
|
(a as f32 + b).round() as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
let info = add.get_function_info();
|
||||||
|
let signature = Signature::from(&info);
|
||||||
|
|
||||||
|
assert_eq!(signature.args().0.len(), 2);
|
||||||
|
assert_eq!(signature.args().0[0], Type::of::<i32>());
|
||||||
|
assert_eq!(signature.args().0[1], Type::of::<f32>());
|
||||||
|
assert_eq!(*signature.return_type(), Type::of::<u32>());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_debug_signature() {
|
||||||
|
let signature = Signature::new(
|
||||||
|
ArgumentSignature::from_iter(vec![Type::of::<&mut String>(), Type::of::<i32>()]),
|
||||||
|
Type::of::<()>(),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
format!("{:?}", signature),
|
||||||
|
"(&mut alloc::string::String, i32) -> ()"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue