Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_reflect/src/func/signature.rs
6599 views
1
//! Function signature types.
2
//!
3
//! Function signatures differ from [`FunctionInfo`] and [`SignatureInfo`] in that they
4
//! are only concerned about the types and order of the arguments and return type of a function.
5
//!
6
//! The names of arguments do not matter,
7
//! nor does any other information about the function such as its name or other attributes.
8
//!
9
//! This makes signatures useful for comparing or hashing functions strictly based on their
10
//! arguments and return type.
11
//!
12
//! [`FunctionInfo`]: crate::func::info::FunctionInfo
13
14
use crate::func::args::ArgInfo;
15
use crate::func::{ArgList, SignatureInfo};
16
use crate::Type;
17
use alloc::boxed::Box;
18
use bevy_platform::collections::Equivalent;
19
use core::borrow::Borrow;
20
use core::fmt::{Debug, Formatter};
21
use core::hash::{Hash, Hasher};
22
use core::ops::{Deref, DerefMut};
23
24
/// The signature of a function.
25
///
26
/// This can be used as a way to compare or hash functions based on their arguments and return type.
27
#[derive(Clone, PartialEq, Eq, Hash)]
28
pub struct Signature {
29
args: ArgumentSignature,
30
ret: Type,
31
}
32
33
impl Signature {
34
/// Create a new function signature with the given argument signature and return type.
35
pub fn new(args: ArgumentSignature, ret: Type) -> Self {
36
Self { args, ret }
37
}
38
39
/// Get the argument signature of the function.
40
pub fn args(&self) -> &ArgumentSignature {
41
&self.args
42
}
43
44
/// Get the return type of the function.
45
pub fn return_type(&self) -> &Type {
46
&self.ret
47
}
48
}
49
50
impl Debug for Signature {
51
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
52
write!(f, "{:?} -> {:?}", self.args, self.ret)
53
}
54
}
55
56
impl<T: Borrow<SignatureInfo>> From<T> for Signature {
57
fn from(info: T) -> Self {
58
let info = info.borrow();
59
Self::new(ArgumentSignature::from(info), *info.return_info().ty())
60
}
61
}
62
63
/// A wrapper around a borrowed [`ArgList`] that can be used as an
64
/// [equivalent] of an [`ArgumentSignature`].
65
///
66
/// [equivalent]: Equivalent
67
pub(super) struct ArgListSignature<'a, 'b>(&'a ArgList<'b>);
68
69
impl Equivalent<ArgumentSignature> for ArgListSignature<'_, '_> {
70
fn equivalent(&self, key: &ArgumentSignature) -> bool {
71
self.len() == key.len() && self.iter().eq(key.iter())
72
}
73
}
74
75
impl<'a, 'b> ArgListSignature<'a, 'b> {
76
pub fn iter(&self) -> impl ExactSizeIterator<Item = &Type> {
77
self.0.iter().map(|arg| {
78
arg.value()
79
.get_represented_type_info()
80
.unwrap_or_else(|| {
81
panic!("no `TypeInfo` found for argument: {:?}", arg);
82
})
83
.ty()
84
})
85
}
86
87
pub fn len(&self) -> usize {
88
self.0.len()
89
}
90
}
91
92
impl Eq for ArgListSignature<'_, '_> {}
93
94
impl PartialEq for ArgListSignature<'_, '_> {
95
fn eq(&self, other: &Self) -> bool {
96
self.len() == other.len() && self.iter().eq(other.iter())
97
}
98
}
99
100
impl Hash for ArgListSignature<'_, '_> {
101
fn hash<H: Hasher>(&self, state: &mut H) {
102
self.0.iter().for_each(|arg| {
103
arg.value()
104
.get_represented_type_info()
105
.unwrap_or_else(|| {
106
panic!("no `TypeInfo` found for argument: {:?}", arg);
107
})
108
.ty()
109
.hash(state);
110
});
111
}
112
}
113
114
impl<'a, 'b> From<&'a ArgList<'b>> for ArgListSignature<'a, 'b> {
115
fn from(args: &'a ArgList<'b>) -> Self {
116
Self(args)
117
}
118
}
119
120
/// The argument-portion of a function signature.
121
///
122
/// For example, given a function signature `(a: i32, b: f32) -> u32`,
123
/// the argument signature would be `(i32, f32)`.
124
///
125
/// This can be used as a way to compare or hash functions based on their arguments.
126
#[derive(Clone)]
127
pub struct ArgumentSignature(Box<[Type]>);
128
129
impl Debug for ArgumentSignature {
130
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
131
let mut tuple = f.debug_tuple("");
132
for ty in self.0.iter() {
133
tuple.field(ty);
134
}
135
tuple.finish()
136
}
137
}
138
139
impl Deref for ArgumentSignature {
140
type Target = [Type];
141
142
fn deref(&self) -> &Self::Target {
143
&self.0
144
}
145
}
146
147
impl DerefMut for ArgumentSignature {
148
fn deref_mut(&mut self) -> &mut Self::Target {
149
&mut self.0
150
}
151
}
152
153
impl Eq for ArgumentSignature {}
154
155
impl PartialEq for ArgumentSignature {
156
fn eq(&self, other: &Self) -> bool {
157
self.0.len() == other.0.len() && self.0.iter().eq(other.0.iter())
158
}
159
}
160
161
impl Hash for ArgumentSignature {
162
fn hash<H: Hasher>(&self, state: &mut H) {
163
self.0.iter().for_each(|ty| ty.hash(state));
164
}
165
}
166
167
impl FromIterator<Type> for ArgumentSignature {
168
fn from_iter<T: IntoIterator<Item = Type>>(iter: T) -> Self {
169
Self(iter.into_iter().collect())
170
}
171
}
172
173
impl<T: Borrow<SignatureInfo>> From<T> for ArgumentSignature {
174
fn from(info: T) -> Self {
175
Self(
176
info.borrow()
177
.args()
178
.iter()
179
.map(ArgInfo::ty)
180
.copied()
181
.collect(),
182
)
183
}
184
}
185
186
impl From<&ArgList<'_>> for ArgumentSignature {
187
fn from(args: &ArgList) -> Self {
188
Self(
189
args.iter()
190
.map(|arg| {
191
arg.value()
192
.get_represented_type_info()
193
.unwrap_or_else(|| {
194
panic!("no `TypeInfo` found for argument: {:?}", arg);
195
})
196
.ty()
197
})
198
.copied()
199
.collect(),
200
)
201
}
202
}
203
204
#[cfg(test)]
205
mod tests {
206
use super::*;
207
use crate::func::TypedFunction;
208
use alloc::{format, string::String, vec};
209
210
#[test]
211
fn should_generate_signature_from_function_info() {
212
fn add(a: i32, b: f32) -> u32 {
213
(a as f32 + b).round() as u32
214
}
215
216
let info = add.get_function_info();
217
let signature = Signature::from(info.base());
218
219
assert_eq!(signature.args().0.len(), 2);
220
assert_eq!(signature.args().0[0], Type::of::<i32>());
221
assert_eq!(signature.args().0[1], Type::of::<f32>());
222
assert_eq!(*signature.return_type(), Type::of::<u32>());
223
}
224
225
#[test]
226
fn should_debug_signature() {
227
let signature = Signature::new(
228
ArgumentSignature::from_iter(vec![Type::of::<&mut String>(), Type::of::<i32>()]),
229
Type::of::<()>(),
230
);
231
232
assert_eq!(
233
format!("{signature:?}"),
234
"(&mut alloc::string::String, i32) -> ()"
235
);
236
}
237
}
238
239