Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_reflect/src/func/info.rs
6599 views
1
use alloc::{borrow::Cow, boxed::Box, vec, vec::Vec};
2
use core::fmt::{Debug, Formatter};
3
4
use crate::{
5
func::args::{ArgCount, ArgCountOutOfBoundsError, ArgInfo, GetOwnership, Ownership},
6
func::signature::ArgumentSignature,
7
func::FunctionOverloadError,
8
type_info::impl_type_methods,
9
Type, TypePath,
10
};
11
12
use variadics_please::all_tuples;
13
14
/// Type information for a [`DynamicFunction`] or [`DynamicFunctionMut`].
15
///
16
/// This information can be retrieved directly from certain functions and closures
17
/// using the [`TypedFunction`] trait, and manually constructed otherwise.
18
///
19
/// It is compromised of one or more [`SignatureInfo`] structs,
20
/// allowing it to represent functions with multiple sets of arguments (i.e. "overloaded functions").
21
///
22
/// [`DynamicFunction`]: crate::func::DynamicFunction
23
/// [`DynamicFunctionMut`]: crate::func::DynamicFunctionMut
24
#[derive(Debug, Clone)]
25
pub struct FunctionInfo {
26
name: Option<Cow<'static, str>>,
27
arg_count: ArgCount,
28
signatures: Box<[SignatureInfo]>,
29
}
30
31
impl FunctionInfo {
32
/// Create a new [`FunctionInfo`] for a function with the given signature.
33
///
34
/// # Panics
35
///
36
/// Panics if the given signature has more than the maximum number of arguments
37
/// as specified by [`ArgCount::MAX_COUNT`].
38
pub fn new(signature: SignatureInfo) -> Self {
39
Self {
40
name: signature.name.clone(),
41
arg_count: ArgCount::new(signature.arg_count()).unwrap(),
42
signatures: vec![signature].into(),
43
}
44
}
45
46
/// Create a new [`FunctionInfo`] from a set of signatures.
47
///
48
/// Returns an error if the given iterator is empty or contains duplicate signatures.
49
pub fn try_from_iter(
50
signatures: impl IntoIterator<Item = SignatureInfo>,
51
) -> Result<Self, FunctionOverloadError> {
52
let mut iter = signatures.into_iter();
53
54
let base = iter.next().ok_or(FunctionOverloadError::MissingSignature)?;
55
56
if base.arg_count() > ArgCount::MAX_COUNT {
57
return Err(FunctionOverloadError::TooManyArguments(
58
ArgumentSignature::from(&base),
59
));
60
}
61
62
let mut info = Self::new(base);
63
64
for signature in iter {
65
if signature.arg_count() > ArgCount::MAX_COUNT {
66
return Err(FunctionOverloadError::TooManyArguments(
67
ArgumentSignature::from(&signature),
68
));
69
}
70
71
info = info.with_overload(signature).map_err(|sig| {
72
FunctionOverloadError::DuplicateSignature(ArgumentSignature::from(&sig))
73
})?;
74
}
75
76
Ok(info)
77
}
78
79
/// The base signature for this function.
80
///
81
/// All functions—including overloaded functions—are guaranteed to have at least one signature.
82
/// The first signature used to define the [`FunctionInfo`] is considered the base signature.
83
pub fn base(&self) -> &SignatureInfo {
84
&self.signatures[0]
85
}
86
87
/// Whether this function is overloaded.
88
///
89
/// This is determined by the existence of multiple signatures.
90
pub fn is_overloaded(&self) -> bool {
91
self.signatures.len() > 1
92
}
93
94
/// Set the name of the function.
95
pub fn with_name(mut self, name: Option<impl Into<Cow<'static, str>>>) -> Self {
96
self.name = name.map(Into::into);
97
self
98
}
99
100
/// The name of the function.
101
///
102
/// For [`DynamicFunctions`] created using [`IntoFunction`] or [`DynamicFunctionMuts`] created using [`IntoFunctionMut`],
103
/// the default name will always be the full path to the function as returned by [`std::any::type_name`],
104
/// unless the function is a closure, anonymous function, or function pointer,
105
/// in which case the name will be `None`.
106
///
107
/// For overloaded functions, this will be the name of the base signature,
108
/// unless manually overwritten using [`Self::with_name`].
109
///
110
/// [`DynamicFunctions`]: crate::func::DynamicFunction
111
/// [`IntoFunction`]: crate::func::IntoFunction
112
/// [`DynamicFunctionMuts`]: crate::func::DynamicFunctionMut
113
/// [`IntoFunctionMut`]: crate::func::IntoFunctionMut
114
pub fn name(&self) -> Option<&Cow<'static, str>> {
115
self.name.as_ref()
116
}
117
118
/// Add a signature to this function.
119
///
120
/// If a signature with the same [`ArgumentSignature`] already exists,
121
/// an error is returned with the given signature.
122
///
123
/// # Panics
124
///
125
/// Panics if the given signature has more than the maximum number of arguments
126
/// as specified by [`ArgCount::MAX_COUNT`].
127
pub fn with_overload(mut self, signature: SignatureInfo) -> Result<Self, SignatureInfo> {
128
let is_duplicate = self.signatures.iter().any(|s| {
129
s.arg_count() == signature.arg_count()
130
&& ArgumentSignature::from(s) == ArgumentSignature::from(&signature)
131
});
132
133
if is_duplicate {
134
return Err(signature);
135
}
136
137
self.arg_count.add(signature.arg_count());
138
self.signatures = IntoIterator::into_iter(self.signatures)
139
.chain(Some(signature))
140
.collect();
141
Ok(self)
142
}
143
144
/// Returns the number of arguments the function expects.
145
///
146
/// For [overloaded] functions that can have a variable number of arguments,
147
/// this will contain the full set of counts for all signatures.
148
///
149
/// [overloaded]: crate::func#overloading-functions
150
pub fn arg_count(&self) -> ArgCount {
151
self.arg_count
152
}
153
154
/// The signatures of the function.
155
///
156
/// This is guaranteed to always contain at least one signature.
157
/// Overloaded functions will contain two or more.
158
pub fn signatures(&self) -> &[SignatureInfo] {
159
&self.signatures
160
}
161
162
/// Returns a wrapper around this info that implements [`Debug`] for pretty-printing the function.
163
///
164
/// This can be useful for more readable debugging and logging.
165
///
166
/// # Example
167
///
168
/// ```
169
/// # use bevy_reflect::func::{FunctionInfo, TypedFunction};
170
/// #
171
/// fn add(a: i32, b: i32) -> i32 {
172
/// a + b
173
/// }
174
///
175
/// let info = add.get_function_info();
176
///
177
/// let pretty = info.pretty_printer();
178
/// assert_eq!(format!("{:?}", pretty), "(_: i32, _: i32) -> i32");
179
/// ```
180
pub fn pretty_printer(&self) -> PrettyPrintFunctionInfo<'_> {
181
PrettyPrintFunctionInfo::new(self)
182
}
183
184
/// Extend this [`FunctionInfo`] with another without checking for duplicates.
185
///
186
/// # Panics
187
///
188
/// Panics if the given signature has more than the maximum number of arguments
189
/// as specified by [`ArgCount::MAX_COUNT`].
190
pub(super) fn extend_unchecked(&mut self, other: FunctionInfo) {
191
if self.name.is_none() {
192
self.name = other.name;
193
}
194
195
let signatures = core::mem::take(&mut self.signatures);
196
self.signatures = IntoIterator::into_iter(signatures)
197
.chain(IntoIterator::into_iter(other.signatures))
198
.collect();
199
self.arg_count = self
200
.signatures
201
.iter()
202
.fold(ArgCount::default(), |mut count, sig| {
203
count.add(sig.arg_count());
204
count
205
});
206
}
207
}
208
209
impl TryFrom<SignatureInfo> for FunctionInfo {
210
type Error = ArgCountOutOfBoundsError;
211
212
fn try_from(signature: SignatureInfo) -> Result<Self, Self::Error> {
213
let count = signature.arg_count();
214
if count > ArgCount::MAX_COUNT {
215
return Err(ArgCountOutOfBoundsError(count));
216
}
217
218
Ok(Self::new(signature))
219
}
220
}
221
222
impl TryFrom<Vec<SignatureInfo>> for FunctionInfo {
223
type Error = FunctionOverloadError;
224
225
fn try_from(signatures: Vec<SignatureInfo>) -> Result<Self, Self::Error> {
226
Self::try_from_iter(signatures)
227
}
228
}
229
230
impl<const N: usize> TryFrom<[SignatureInfo; N]> for FunctionInfo {
231
type Error = FunctionOverloadError;
232
233
fn try_from(signatures: [SignatureInfo; N]) -> Result<Self, Self::Error> {
234
Self::try_from_iter(signatures)
235
}
236
}
237
238
/// Type information for the signature of a [`DynamicFunction`] or [`DynamicFunctionMut`].
239
///
240
/// Every [`FunctionInfo`] contains one or more [`SignatureInfo`]s.
241
///
242
/// [`DynamicFunction`]: crate::func::DynamicFunction
243
/// [`DynamicFunctionMut`]: crate::func::DynamicFunctionMut
244
#[derive(Debug, Clone)]
245
pub struct SignatureInfo {
246
name: Option<Cow<'static, str>>,
247
args: Box<[ArgInfo]>,
248
return_info: ReturnInfo,
249
}
250
251
impl SignatureInfo {
252
/// Create a new [`SignatureInfo`] for a function with the given name.
253
pub fn named(name: impl Into<Cow<'static, str>>) -> Self {
254
Self {
255
name: Some(name.into()),
256
args: Box::new([]),
257
return_info: ReturnInfo::new::<()>(),
258
}
259
}
260
261
/// Create a new [`SignatureInfo`] with no name.
262
///
263
/// For the purposes of debugging and [registration],
264
/// it's recommended to use [`Self::named`] instead.
265
///
266
/// [registration]: crate::func::FunctionRegistry
267
pub fn anonymous() -> Self {
268
Self {
269
name: None,
270
args: Box::new([]),
271
return_info: ReturnInfo::new::<()>(),
272
}
273
}
274
275
/// Set the name of the function.
276
pub fn with_name(mut self, name: impl Into<Cow<'static, str>>) -> Self {
277
self.name = Some(name.into());
278
self
279
}
280
281
/// Push an argument onto the function's argument list.
282
///
283
/// The order in which this method is called matters as it will determine the index of the argument
284
/// based on the current number of arguments.
285
pub fn with_arg<T: TypePath + GetOwnership>(
286
mut self,
287
name: impl Into<Cow<'static, str>>,
288
) -> Self {
289
let index = self.args.len();
290
self.args = IntoIterator::into_iter(self.args)
291
.chain(Some(ArgInfo::new::<T>(index).with_name(name)))
292
.collect();
293
self
294
}
295
296
/// Set the arguments of the function.
297
///
298
/// This will completely replace any existing arguments.
299
///
300
/// It's preferable to use [`Self::with_arg`] to add arguments to the function
301
/// as it will automatically set the index of the argument.
302
pub fn with_args(mut self, args: Vec<ArgInfo>) -> Self {
303
self.args = IntoIterator::into_iter(self.args).chain(args).collect();
304
self
305
}
306
307
/// Set the [return information] of the function.
308
///
309
/// To manually set the [`ReturnInfo`] of the function, see [`Self::with_return_info`].
310
///
311
/// [return information]: ReturnInfo
312
pub fn with_return<T: TypePath + GetOwnership>(mut self) -> Self {
313
self.return_info = ReturnInfo::new::<T>();
314
self
315
}
316
317
/// Set the [return information] of the function.
318
///
319
/// This will completely replace any existing return information.
320
///
321
/// For a simpler, static version of this method, see [`Self::with_return`].
322
///
323
/// [return information]: ReturnInfo
324
pub fn with_return_info(mut self, return_info: ReturnInfo) -> Self {
325
self.return_info = return_info;
326
self
327
}
328
329
/// The name of the function.
330
///
331
/// For [`DynamicFunctions`] created using [`IntoFunction`] or [`DynamicFunctionMuts`] created using [`IntoFunctionMut`],
332
/// the default name will always be the full path to the function as returned by [`core::any::type_name`],
333
/// unless the function is a closure, anonymous function, or function pointer,
334
/// in which case the name will be `None`.
335
///
336
/// [`DynamicFunctions`]: crate::func::DynamicFunction
337
/// [`IntoFunction`]: crate::func::IntoFunction
338
/// [`DynamicFunctionMuts`]: crate::func::DynamicFunctionMut
339
/// [`IntoFunctionMut`]: crate::func::IntoFunctionMut
340
pub fn name(&self) -> Option<&Cow<'static, str>> {
341
self.name.as_ref()
342
}
343
344
/// The arguments of the function.
345
pub fn args(&self) -> &[ArgInfo] {
346
&self.args
347
}
348
349
/// The number of arguments the function takes.
350
pub fn arg_count(&self) -> usize {
351
self.args.len()
352
}
353
354
/// The return information of the function.
355
pub fn return_info(&self) -> &ReturnInfo {
356
&self.return_info
357
}
358
}
359
360
/// Information about the return type of a [`DynamicFunction`] or [`DynamicFunctionMut`].
361
///
362
/// [`DynamicFunction`]: crate::func::DynamicFunction
363
/// [`DynamicFunctionMut`]: crate::func::DynamicFunctionMut
364
#[derive(Debug, Clone)]
365
pub struct ReturnInfo {
366
ty: Type,
367
ownership: Ownership,
368
}
369
370
impl ReturnInfo {
371
/// Create a new [`ReturnInfo`] representing the given type, `T`.
372
pub fn new<T: TypePath + GetOwnership>() -> Self {
373
Self {
374
ty: Type::of::<T>(),
375
ownership: T::ownership(),
376
}
377
}
378
379
impl_type_methods!(ty);
380
381
/// The ownership of this type.
382
pub fn ownership(&self) -> Ownership {
383
self.ownership
384
}
385
}
386
387
/// A wrapper around [`FunctionInfo`] that implements [`Debug`] for pretty-printing function information.
388
///
389
/// # Example
390
///
391
/// ```
392
/// # use bevy_reflect::func::{FunctionInfo, PrettyPrintFunctionInfo, TypedFunction};
393
/// #
394
/// fn add(a: i32, b: i32) -> i32 {
395
/// a + b
396
/// }
397
///
398
/// let info = add.get_function_info();
399
///
400
/// let pretty = PrettyPrintFunctionInfo::new(&info);
401
/// assert_eq!(format!("{:?}", pretty), "(_: i32, _: i32) -> i32");
402
/// ```
403
pub struct PrettyPrintFunctionInfo<'a> {
404
info: &'a FunctionInfo,
405
include_fn_token: bool,
406
include_name: bool,
407
}
408
409
impl<'a> PrettyPrintFunctionInfo<'a> {
410
/// Create a new pretty-printer for the given [`FunctionInfo`].
411
pub fn new(info: &'a FunctionInfo) -> Self {
412
Self {
413
info,
414
include_fn_token: false,
415
include_name: false,
416
}
417
}
418
419
/// Include the function name in the pretty-printed output.
420
pub fn include_name(mut self) -> Self {
421
self.include_name = true;
422
self
423
}
424
425
/// Include the `fn` token in the pretty-printed output.
426
pub fn include_fn_token(mut self) -> Self {
427
self.include_fn_token = true;
428
self
429
}
430
}
431
432
impl<'a> Debug for PrettyPrintFunctionInfo<'a> {
433
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
434
if self.include_fn_token {
435
write!(f, "fn")?;
436
437
if self.include_name {
438
write!(f, " ")?;
439
}
440
}
441
442
match (self.include_name, self.info.name()) {
443
(true, Some(name)) => write!(f, "{name}")?,
444
(true, None) => write!(f, "_")?,
445
_ => {}
446
}
447
448
if self.info.is_overloaded() {
449
// `{(arg0: i32, arg1: i32) -> (), (arg0: f32, arg1: f32) -> ()}`
450
let mut set = f.debug_set();
451
for signature in self.info.signatures() {
452
set.entry(&PrettyPrintSignatureInfo::new(signature));
453
}
454
set.finish()
455
} else {
456
// `(arg0: i32, arg1: i32) -> ()`
457
PrettyPrintSignatureInfo::new(self.info.base()).fmt(f)
458
}
459
}
460
}
461
462
/// A wrapper around [`SignatureInfo`] that implements [`Debug`] for pretty-printing function signature information.
463
///
464
/// # Example
465
///
466
/// ```
467
/// # use bevy_reflect::func::{FunctionInfo, PrettyPrintSignatureInfo, TypedFunction};
468
/// #
469
/// fn add(a: i32, b: i32) -> i32 {
470
/// a + b
471
/// }
472
///
473
/// let info = add.get_function_info();
474
///
475
/// let pretty = PrettyPrintSignatureInfo::new(info.base());
476
/// assert_eq!(format!("{:?}", pretty), "(_: i32, _: i32) -> i32");
477
/// ```
478
pub struct PrettyPrintSignatureInfo<'a> {
479
info: &'a SignatureInfo,
480
include_fn_token: bool,
481
include_name: bool,
482
}
483
484
impl<'a> PrettyPrintSignatureInfo<'a> {
485
/// Create a new pretty-printer for the given [`SignatureInfo`].
486
pub fn new(info: &'a SignatureInfo) -> Self {
487
Self {
488
info,
489
include_fn_token: false,
490
include_name: false,
491
}
492
}
493
494
/// Include the function name in the pretty-printed output.
495
pub fn include_name(mut self) -> Self {
496
self.include_name = true;
497
self
498
}
499
500
/// Include the `fn` token in the pretty-printed output.
501
pub fn include_fn_token(mut self) -> Self {
502
self.include_fn_token = true;
503
self
504
}
505
}
506
507
impl<'a> Debug for PrettyPrintSignatureInfo<'a> {
508
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
509
if self.include_fn_token {
510
write!(f, "fn")?;
511
512
if self.include_name {
513
write!(f, " ")?;
514
}
515
}
516
517
match (self.include_name, self.info.name()) {
518
(true, Some(name)) => write!(f, "{name}")?,
519
(true, None) => write!(f, "_")?,
520
_ => {}
521
}
522
523
write!(f, "(")?;
524
525
// We manually write the args instead of using `DebugTuple` to avoid trailing commas
526
// and (when used with `{:#?}`) unnecessary newlines
527
for (index, arg) in self.info.args().iter().enumerate() {
528
if index > 0 {
529
write!(f, ", ")?;
530
}
531
532
let name = arg.name().unwrap_or("_");
533
let ty = arg.type_path();
534
write!(f, "{name}: {ty}")?;
535
}
536
537
let ret = self.info.return_info().type_path();
538
write!(f, ") -> {ret}")
539
}
540
}
541
542
/// A static accessor to compile-time type information for functions.
543
///
544
/// This is the equivalent of [`Typed`], but for function.
545
///
546
/// # Blanket Implementation
547
///
548
/// This trait has a blanket implementation that covers:
549
/// - Functions and methods defined with the `fn` keyword
550
/// - Anonymous functions
551
/// - Function pointers
552
/// - Closures that capture immutable references to their environment
553
/// - Closures that capture mutable references to their environment
554
/// - Closures that take ownership of captured variables
555
///
556
/// For each of the above cases, the function signature may only have up to 15 arguments,
557
/// not including an optional receiver argument (often `&self` or `&mut self`).
558
/// This optional receiver argument may be either a mutable or immutable reference to a type.
559
/// If the return type is also a reference, its lifetime will be bound to the lifetime of this receiver.
560
///
561
/// See the [module-level documentation] for more information on valid signatures.
562
///
563
/// Arguments and the return type are expected to implement both [`GetOwnership`] and [`TypePath`].
564
/// By default, these traits are automatically implemented when using the `Reflect` [derive macro].
565
///
566
/// # Example
567
///
568
/// ```
569
/// # use bevy_reflect::func::{ArgList, ReflectFnMut, TypedFunction};
570
/// #
571
/// fn print(value: String) {
572
/// println!("{}", value);
573
/// }
574
///
575
/// let info = print.get_function_info();
576
/// assert!(info.name().unwrap().ends_with("print"));
577
/// assert!(info.arg_count().contains(1));
578
/// assert_eq!(info.base().args()[0].type_path(), "alloc::string::String");
579
/// assert_eq!(info.base().return_info().type_path(), "()");
580
/// ```
581
///
582
/// # Trait Parameters
583
///
584
/// This trait has a `Marker` type parameter that is used to get around issues with
585
/// [unconstrained type parameters] when defining impls with generic arguments or return types.
586
/// This `Marker` can be any type, provided it doesn't conflict with other implementations.
587
///
588
/// [module-level documentation]: crate::func
589
/// [`Typed`]: crate::Typed
590
/// [unconstrained type parameters]: https://doc.rust-lang.org/error_codes/E0207.html
591
pub trait TypedFunction<Marker> {
592
/// Get the [`FunctionInfo`] for this type.
593
fn function_info() -> FunctionInfo;
594
595
/// Get the [`FunctionInfo`] for this type.
596
fn get_function_info(&self) -> FunctionInfo {
597
Self::function_info()
598
}
599
}
600
601
/// Helper macro for implementing [`TypedFunction`] on Rust functions.
602
///
603
/// This currently implements it for the following signatures (where `argX` may be any of `T`, `&T`, or `&mut T`):
604
/// - `FnMut(arg0, arg1, ..., argN) -> R`
605
/// - `FnMut(&Receiver, arg0, arg1, ..., argN) -> &R`
606
/// - `FnMut(&mut Receiver, arg0, arg1, ..., argN) -> &mut R`
607
/// - `FnMut(&mut Receiver, arg0, arg1, ..., argN) -> &R`
608
macro_rules! impl_typed_function {
609
($(($Arg:ident, $arg:ident)),*) => {
610
// === (...) -> ReturnType === //
611
impl<$($Arg,)* ReturnType, Function> TypedFunction<fn($($Arg),*) -> [ReturnType]> for Function
612
where
613
$($Arg: TypePath + GetOwnership,)*
614
ReturnType: TypePath + GetOwnership,
615
Function: FnMut($($Arg),*) -> ReturnType,
616
{
617
fn function_info() -> FunctionInfo {
618
FunctionInfo::new(
619
create_info::<Function>()
620
.with_args({
621
let mut _index = 0;
622
vec![
623
$(ArgInfo::new::<$Arg>({
624
_index += 1;
625
_index - 1
626
}),)*
627
]
628
})
629
.with_return_info(ReturnInfo::new::<ReturnType>())
630
)
631
}
632
}
633
634
// === (&self, ...) -> &ReturnType === //
635
impl<Receiver, $($Arg,)* ReturnType, Function> TypedFunction<fn(&Receiver, $($Arg),*) -> &ReturnType> for Function
636
where
637
for<'a> &'a Receiver: TypePath + GetOwnership,
638
$($Arg: TypePath + GetOwnership,)*
639
for<'a> &'a ReturnType: TypePath + GetOwnership,
640
Function: for<'a> FnMut(&'a Receiver, $($Arg),*) -> &'a ReturnType,
641
{
642
fn function_info() -> FunctionInfo {
643
FunctionInfo::new(
644
create_info::<Function>()
645
.with_args({
646
let mut _index = 1;
647
vec![
648
ArgInfo::new::<&Receiver>(0),
649
$($crate::func::args::ArgInfo::new::<$Arg>({
650
_index += 1;
651
_index - 1
652
}),)*
653
]
654
})
655
.with_return_info(ReturnInfo::new::<&ReturnType>())
656
)
657
}
658
}
659
660
// === (&mut self, ...) -> &mut ReturnType === //
661
impl<Receiver, $($Arg,)* ReturnType, Function> TypedFunction<fn(&mut Receiver, $($Arg),*) -> &mut ReturnType> for Function
662
where
663
for<'a> &'a mut Receiver: TypePath + GetOwnership,
664
$($Arg: TypePath + GetOwnership,)*
665
for<'a> &'a mut ReturnType: TypePath + GetOwnership,
666
Function: for<'a> FnMut(&'a mut Receiver, $($Arg),*) -> &'a mut ReturnType,
667
{
668
fn function_info() -> FunctionInfo {
669
FunctionInfo::new(
670
create_info::<Function>()
671
.with_args({
672
let mut _index = 1;
673
vec![
674
ArgInfo::new::<&mut Receiver>(0),
675
$(ArgInfo::new::<$Arg>({
676
_index += 1;
677
_index - 1
678
}),)*
679
]
680
})
681
.with_return_info(ReturnInfo::new::<&mut ReturnType>())
682
)
683
}
684
}
685
686
// === (&mut self, ...) -> &ReturnType === //
687
impl<Receiver, $($Arg,)* ReturnType, Function> TypedFunction<fn(&mut Receiver, $($Arg),*) -> &ReturnType> for Function
688
where
689
for<'a> &'a mut Receiver: TypePath + GetOwnership,
690
$($Arg: TypePath + GetOwnership,)*
691
for<'a> &'a ReturnType: TypePath + GetOwnership,
692
Function: for<'a> FnMut(&'a mut Receiver, $($Arg),*) -> &'a ReturnType,
693
{
694
fn function_info() -> FunctionInfo {
695
FunctionInfo::new(
696
create_info::<Function>()
697
.with_args({
698
let mut _index = 1;
699
vec![
700
ArgInfo::new::<&mut Receiver>(0),
701
$(ArgInfo::new::<$Arg>({
702
_index += 1;
703
_index - 1
704
}),)*
705
]
706
})
707
.with_return_info(ReturnInfo::new::<&ReturnType>())
708
)
709
}
710
}
711
};
712
}
713
714
all_tuples!(impl_typed_function, 0, 15, Arg, arg);
715
716
/// Helper function for creating [`FunctionInfo`] with the proper name value.
717
///
718
/// Names are only given if:
719
/// - The function is not a closure
720
/// - The function is not a function pointer
721
/// - The function is not an anonymous function
722
///
723
/// This function relies on the [`type_name`] of `F` to determine this.
724
/// The following table describes the behavior for different types of functions:
725
///
726
/// | Category | `type_name` | `FunctionInfo::name` |
727
/// | ------------------ | ----------------------- | ----------------------- |
728
/// | Named function | `foo::bar::baz` | `Some("foo::bar::baz")` |
729
/// | Closure | `foo::bar::{{closure}}` | `None` |
730
/// | Anonymous function | `foo::bar::{{closure}}` | `None` |
731
/// | Function pointer | `fn() -> String` | `None` |
732
///
733
/// [`type_name`]: core::any::type_name
734
fn create_info<F>() -> SignatureInfo {
735
let name = core::any::type_name::<F>();
736
737
if name.ends_with("{{closure}}") || name.starts_with("fn(") {
738
SignatureInfo::anonymous()
739
} else {
740
SignatureInfo::named(name)
741
}
742
}
743
744
#[cfg(test)]
745
mod tests {
746
use super::*;
747
748
#[test]
749
fn should_create_function_info() {
750
fn add(a: i32, b: i32) -> i32 {
751
a + b
752
}
753
754
// Sanity check:
755
assert_eq!(
756
core::any::type_name_of_val(&add),
757
"bevy_reflect::func::info::tests::should_create_function_info::add"
758
);
759
760
let info = add.get_function_info();
761
assert_eq!(
762
info.name().unwrap(),
763
"bevy_reflect::func::info::tests::should_create_function_info::add"
764
);
765
assert_eq!(info.base().arg_count(), 2);
766
assert_eq!(info.base().args()[0].type_path(), "i32");
767
assert_eq!(info.base().args()[1].type_path(), "i32");
768
assert_eq!(info.base().return_info().type_path(), "i32");
769
}
770
771
#[test]
772
fn should_create_function_pointer_info() {
773
fn add(a: i32, b: i32) -> i32 {
774
a + b
775
}
776
777
let add = add as fn(i32, i32) -> i32;
778
779
// Sanity check:
780
assert_eq!(core::any::type_name_of_val(&add), "fn(i32, i32) -> i32");
781
782
let info = add.get_function_info();
783
assert!(info.name().is_none());
784
assert_eq!(info.base().arg_count(), 2);
785
assert_eq!(info.base().args()[0].type_path(), "i32");
786
assert_eq!(info.base().args()[1].type_path(), "i32");
787
assert_eq!(info.base().return_info().type_path(), "i32");
788
}
789
790
#[test]
791
fn should_create_anonymous_function_info() {
792
let add = |a: i32, b: i32| a + b;
793
794
// Sanity check:
795
assert_eq!(
796
core::any::type_name_of_val(&add),
797
"bevy_reflect::func::info::tests::should_create_anonymous_function_info::{{closure}}"
798
);
799
800
let info = add.get_function_info();
801
assert!(info.name().is_none());
802
assert_eq!(info.base().arg_count(), 2);
803
assert_eq!(info.base().args()[0].type_path(), "i32");
804
assert_eq!(info.base().args()[1].type_path(), "i32");
805
assert_eq!(info.base().return_info().type_path(), "i32");
806
}
807
808
#[test]
809
fn should_create_closure_info() {
810
let mut total = 0;
811
let add = |a: i32, b: i32| total = a + b;
812
813
// Sanity check:
814
assert_eq!(
815
core::any::type_name_of_val(&add),
816
"bevy_reflect::func::info::tests::should_create_closure_info::{{closure}}"
817
);
818
819
let info = add.get_function_info();
820
assert!(info.name().is_none());
821
assert_eq!(info.base().arg_count(), 2);
822
assert_eq!(info.base().args()[0].type_path(), "i32");
823
assert_eq!(info.base().args()[1].type_path(), "i32");
824
assert_eq!(info.base().return_info().type_path(), "()");
825
}
826
827
#[test]
828
fn should_pretty_print_info() {
829
// fn add(a: i32, b: i32) -> i32 {
830
// a + b
831
// }
832
//
833
// let info = add.get_function_info().with_name("add");
834
//
835
// let pretty = info.pretty_printer();
836
// assert_eq!(format!("{:?}", pretty), "(_: i32, _: i32) -> i32");
837
//
838
// let pretty = info.pretty_printer().include_fn_token();
839
// assert_eq!(format!("{:?}", pretty), "fn(_: i32, _: i32) -> i32");
840
//
841
// let pretty = info.pretty_printer().include_name();
842
// assert_eq!(format!("{:?}", pretty), "add(_: i32, _: i32) -> i32");
843
//
844
// let pretty = info.pretty_printer().include_fn_token().include_name();
845
// assert_eq!(format!("{:?}", pretty), "fn add(_: i32, _: i32) -> i32");
846
}
847
}
848
849