Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_reflect/src/lib.rs
6598 views
1
#![cfg_attr(
2
any(docsrs, docsrs_dep),
3
expect(
4
internal_features,
5
reason = "rustdoc_internals is needed for fake_variadic"
6
)
7
)]
8
#![cfg_attr(any(docsrs, docsrs_dep), feature(doc_auto_cfg, rustdoc_internals))]
9
#![doc(
10
html_logo_url = "https://bevy.org/assets/icon.png",
11
html_favicon_url = "https://bevy.org/assets/icon.png"
12
)]
13
14
//! Reflection in Rust.
15
//!
16
//! [Reflection] is a powerful tool provided within many programming languages
17
//! that allows for meta-programming: using information _about_ the program to
18
//! _affect_ the program.
19
//! In other words, reflection allows us to inspect the program itself, its
20
//! syntax, and its type information at runtime.
21
//!
22
//! This crate adds this missing reflection functionality to Rust.
23
//! Though it was made with the [Bevy] game engine in mind,
24
//! it's a general-purpose solution that can be used in any Rust project.
25
//!
26
//! At a very high level, this crate allows you to:
27
//! * Dynamically interact with Rust values
28
//! * Access type metadata at runtime
29
//! * Serialize and deserialize (i.e. save and load) data
30
//!
31
//! It's important to note that because of missing features in Rust,
32
//! there are some [limitations] with this crate.
33
//!
34
//! # The `Reflect` and `PartialReflect` traits
35
//!
36
//! At the root of [`bevy_reflect`] is the [`PartialReflect`] trait.
37
//!
38
//! Its purpose is to allow dynamic [introspection] of values,
39
//! following Rust's type system through a system of [subtraits].
40
//!
41
//! Its primary purpose is to allow all implementors to be passed around
42
//! as a `dyn PartialReflect` trait object in one of the following forms:
43
//! * `&dyn PartialReflect`
44
//! * `&mut dyn PartialReflect`
45
//! * `Box<dyn PartialReflect>`
46
//!
47
//! This allows values of types implementing `PartialReflect`
48
//! to be operated upon completely dynamically (at a small [runtime cost]).
49
//!
50
//! Building on `PartialReflect` is the [`Reflect`] trait.
51
//!
52
//! `PartialReflect` is a supertrait of `Reflect`
53
//! so any type implementing `Reflect` implements `PartialReflect` by definition.
54
//! `dyn Reflect` trait objects can be used similarly to `dyn PartialReflect`,
55
//! but `Reflect` is also often used in trait bounds (like `T: Reflect`).
56
//!
57
//! The distinction between `PartialReflect` and `Reflect` is summarized in the following:
58
//! * `PartialReflect` is a trait for interacting with values under `bevy_reflect`'s data model.
59
//! This means values implementing `PartialReflect` can be dynamically constructed and introspected.
60
//! * The `Reflect` trait, however, ensures that the interface exposed by `PartialReflect`
61
//! on types which additionally implement `Reflect` mirrors the structure of a single Rust type.
62
//! * This means `dyn Reflect` trait objects can be directly downcast to concrete types,
63
//! where `dyn PartialReflect` trait object cannot.
64
//! * `Reflect`, since it provides a stronger type-correctness guarantee,
65
//! is the trait used to interact with [the type registry].
66
//!
67
//! ## Converting between `PartialReflect` and `Reflect`
68
//!
69
//! Since `T: Reflect` implies `T: PartialReflect`, conversion from a `dyn Reflect` to a `dyn PartialReflect`
70
//! trait object (upcasting) is infallible and can be performed with one of the following methods.
71
//! Note that these are temporary while [the language feature for dyn upcasting coercion] is experimental:
72
//! * [`PartialReflect::as_partial_reflect`] for `&dyn PartialReflect`
73
//! * [`PartialReflect::as_partial_reflect_mut`] for `&mut dyn PartialReflect`
74
//! * [`PartialReflect::into_partial_reflect`] for `Box<dyn PartialReflect>`
75
//!
76
//! For conversion in the other direction — downcasting `dyn PartialReflect` to `dyn Reflect` —
77
//! there are fallible methods:
78
//! * [`PartialReflect::try_as_reflect`] for `&dyn Reflect`
79
//! * [`PartialReflect::try_as_reflect_mut`] for `&mut dyn Reflect`
80
//! * [`PartialReflect::try_into_reflect`] for `Box<dyn Reflect>`
81
//!
82
//! Additionally, [`FromReflect::from_reflect`] can be used to convert a `dyn PartialReflect` to a concrete type
83
//! which implements `Reflect`.
84
//!
85
//! # Implementing `Reflect`
86
//!
87
//! Implementing `Reflect` (and `PartialReflect`) is easily done using the provided [derive macro]:
88
//!
89
//! ```
90
//! # use bevy_reflect::Reflect;
91
//! #[derive(Reflect)]
92
//! struct MyStruct {
93
//! foo: i32
94
//! }
95
//! ```
96
//!
97
//! This will automatically generate the implementation of `Reflect` for any struct or enum.
98
//!
99
//! It will also generate other very important trait implementations used for reflection:
100
//! * [`GetTypeRegistration`]
101
//! * [`Typed`]
102
//! * [`Struct`], [`TupleStruct`], or [`Enum`] depending on the type
103
//!
104
//! ## Requirements
105
//!
106
//! We can implement `Reflect` on any type that satisfies _both_ of the following conditions:
107
//! * The type implements `Any`, `Send`, and `Sync`.
108
//! For the `Any` requirement to be satisfied, the type itself must have a [`'static` lifetime].
109
//! * All fields and sub-elements themselves implement `Reflect`
110
//! (see the [derive macro documentation] for details on how to ignore certain fields when deriving).
111
//!
112
//! Additionally, using the derive macro on enums requires a third condition to be met:
113
//! * All fields and sub-elements must implement [`FromReflect`]—
114
//! another important reflection trait discussed in a later section.
115
//!
116
//! # The Reflection Subtraits
117
//!
118
//! Since [`PartialReflect`] is meant to cover any and every type, this crate also comes with a few
119
//! more traits to accompany `PartialReflect` and provide more specific interactions.
120
//! We refer to these traits as the _reflection subtraits_ since they all have `PartialReflect` as a supertrait.
121
//! The current list of reflection subtraits include:
122
//! * [`Tuple`]
123
//! * [`Array`]
124
//! * [`List`]
125
//! * [`Set`]
126
//! * [`Map`]
127
//! * [`Struct`]
128
//! * [`TupleStruct`]
129
//! * [`Enum`]
130
//! * [`Function`] (requires the `functions` feature)
131
//!
132
//! As mentioned previously, the last three are automatically implemented by the [derive macro].
133
//!
134
//! Each of these traits come with their own methods specific to their respective category.
135
//! For example, we can access our struct's fields by name using the [`Struct::field`] method.
136
//!
137
//! ```
138
//! # use bevy_reflect::{PartialReflect, Reflect, Struct};
139
//! # #[derive(Reflect)]
140
//! # struct MyStruct {
141
//! # foo: i32
142
//! # }
143
//! let my_struct: Box<dyn Struct> = Box::new(MyStruct {
144
//! foo: 123
145
//! });
146
//! let foo: &dyn PartialReflect = my_struct.field("foo").unwrap();
147
//! assert_eq!(Some(&123), foo.try_downcast_ref::<i32>());
148
//! ```
149
//!
150
//! Since most data is passed around as `dyn PartialReflect` or `dyn Reflect` trait objects,
151
//! the `PartialReflect` trait has methods for going to and from these subtraits.
152
//!
153
//! [`PartialReflect::reflect_kind`], [`PartialReflect::reflect_ref`],
154
//! [`PartialReflect::reflect_mut`], and [`PartialReflect::reflect_owned`] all return
155
//! an enum that respectively contains zero-sized, immutable, mutable, and owned access to the type as a subtrait object.
156
//!
157
//! For example, we can get out a `dyn Tuple` from our reflected tuple type using one of these methods.
158
//!
159
//! ```
160
//! # use bevy_reflect::{PartialReflect, ReflectRef};
161
//! let my_tuple: Box<dyn PartialReflect> = Box::new((1, 2, 3));
162
//! let my_tuple = my_tuple.reflect_ref().as_tuple().unwrap();
163
//! assert_eq!(3, my_tuple.field_len());
164
//! ```
165
//!
166
//! And to go back to a general-purpose `dyn PartialReflect`,
167
//! we can just use the matching [`PartialReflect::as_partial_reflect`], [`PartialReflect::as_partial_reflect_mut`],
168
//! or [`PartialReflect::into_partial_reflect`] methods.
169
//!
170
//! ## Opaque Types
171
//!
172
//! Some types don't fall under a particular subtrait.
173
//!
174
//! These types hide their internal structure to reflection,
175
//! either because it is not possible, difficult, or not useful to reflect its internals.
176
//! Such types are known as _opaque_ types.
177
//!
178
//! This includes truly opaque types like `String` or `Instant`,
179
//! but also includes all the primitive types (e.g. `bool`, `usize`, etc.)
180
//! since they can't be broken down any further.
181
//!
182
//! # Dynamic Types
183
//!
184
//! Each subtrait comes with a corresponding _dynamic_ type.
185
//!
186
//! The available dynamic types are:
187
//! * [`DynamicTuple`]
188
//! * [`DynamicArray`]
189
//! * [`DynamicList`]
190
//! * [`DynamicMap`]
191
//! * [`DynamicStruct`]
192
//! * [`DynamicTupleStruct`]
193
//! * [`DynamicEnum`]
194
//!
195
//! These dynamic types may contain any arbitrary reflected data.
196
//!
197
//! ```
198
//! # use bevy_reflect::{DynamicStruct, Struct};
199
//! let mut data = DynamicStruct::default();
200
//! data.insert("foo", 123_i32);
201
//! assert_eq!(Some(&123), data.field("foo").unwrap().try_downcast_ref::<i32>())
202
//! ```
203
//!
204
//! They are most commonly used as "proxies" for other types,
205
//! where they contain the same data as— and therefore, represent— a concrete type.
206
//! The [`PartialReflect::to_dynamic`] method will return a dynamic type for all non-opaque types,
207
//! allowing all types to essentially be "cloned" into a dynamic type.
208
//! And since dynamic types themselves implement [`PartialReflect`],
209
//! we may pass them around just like most other reflected types.
210
//!
211
//! ```
212
//! # use bevy_reflect::{DynamicStruct, PartialReflect, Reflect};
213
//! # #[derive(Reflect)]
214
//! # struct MyStruct {
215
//! # foo: i32
216
//! # }
217
//! let original: Box<dyn Reflect> = Box::new(MyStruct {
218
//! foo: 123
219
//! });
220
//!
221
//! // `dynamic` will be a `DynamicStruct` representing a `MyStruct`
222
//! let dynamic: Box<dyn PartialReflect> = original.to_dynamic();
223
//! assert!(dynamic.represents::<MyStruct>());
224
//! ```
225
//!
226
//! ## Patching
227
//!
228
//! These dynamic types come in handy when needing to apply multiple changes to another type.
229
//! This is known as "patching" and is done using the [`PartialReflect::apply`] and [`PartialReflect::try_apply`] methods.
230
//!
231
//! ```
232
//! # use bevy_reflect::{DynamicEnum, PartialReflect};
233
//! let mut value = Some(123_i32);
234
//! let patch = DynamicEnum::new("None", ());
235
//! value.apply(&patch);
236
//! assert_eq!(None, value);
237
//! ```
238
//!
239
//! ## `FromReflect`
240
//!
241
//! It's important to remember that dynamic types are _not_ the concrete type they may be representing.
242
//! A common mistake is to treat them like such when trying to cast back to the original type
243
//! or when trying to make use of a reflected trait which expects the actual type.
244
//!
245
//! ```should_panic
246
//! # use bevy_reflect::{DynamicStruct, PartialReflect, Reflect};
247
//! # #[derive(Reflect)]
248
//! # struct MyStruct {
249
//! # foo: i32
250
//! # }
251
//! let original: Box<dyn Reflect> = Box::new(MyStruct {
252
//! foo: 123
253
//! });
254
//!
255
//! let dynamic: Box<dyn PartialReflect> = original.to_dynamic();
256
//! let value = dynamic.try_take::<MyStruct>().unwrap(); // PANIC!
257
//! ```
258
//!
259
//! To resolve this issue, we'll need to convert the dynamic type to the concrete one.
260
//! This is where [`FromReflect`] comes in.
261
//!
262
//! `FromReflect` is a trait that allows an instance of a type to be generated from a
263
//! dynamic representation— even partial ones.
264
//! And since the [`FromReflect::from_reflect`] method takes the data by reference,
265
//! this can be used to effectively clone data (to an extent).
266
//!
267
//! It is automatically implemented when [deriving `Reflect`] on a type unless opted out of
268
//! using `#[reflect(from_reflect = false)]` on the item.
269
//!
270
//! ```
271
//! # use bevy_reflect::{FromReflect, PartialReflect, Reflect};
272
//! #[derive(Reflect)]
273
//! struct MyStruct {
274
//! foo: i32
275
//! }
276
//! let original: Box<dyn Reflect> = Box::new(MyStruct {
277
//! foo: 123
278
//! });
279
//!
280
//! let dynamic: Box<dyn PartialReflect> = original.to_dynamic();
281
//! let value = <MyStruct as FromReflect>::from_reflect(&*dynamic).unwrap(); // OK!
282
//! ```
283
//!
284
//! When deriving, all active fields and sub-elements must also implement `FromReflect`.
285
//!
286
//! Fields can be given default values for when a field is missing in the passed value or even ignored.
287
//! Ignored fields must either implement [`Default`] or have a default function specified
288
//! using `#[reflect(default = "path::to::function")]`.
289
//!
290
//! See the [derive macro documentation](derive@crate::FromReflect) for details.
291
//!
292
//! All primitives and simple types implement `FromReflect` by relying on their [`Default`] implementation.
293
//!
294
//! # Path navigation
295
//!
296
//! The [`GetPath`] trait allows accessing arbitrary nested fields of an [`PartialReflect`] type.
297
//!
298
//! Using `GetPath`, it is possible to use a path string to access a specific field
299
//! of a reflected type.
300
//!
301
//! ```
302
//! # use bevy_reflect::{Reflect, GetPath};
303
//! #[derive(Reflect)]
304
//! struct MyStruct {
305
//! value: Vec<Option<u32>>
306
//! }
307
//!
308
//! let my_struct = MyStruct {
309
//! value: vec![None, None, Some(123)],
310
//! };
311
//! assert_eq!(
312
//! my_struct.path::<u32>(".value[2].0").unwrap(),
313
//! &123,
314
//! );
315
//! ```
316
//!
317
//! # Type Registration
318
//!
319
//! This crate also comes with a [`TypeRegistry`] that can be used to store and retrieve additional type metadata at runtime,
320
//! such as helper types and trait implementations.
321
//!
322
//! The [derive macro] for [`Reflect`] also generates an implementation of the [`GetTypeRegistration`] trait,
323
//! which is used by the registry to generate a [`TypeRegistration`] struct for that type.
324
//! We can then register additional [type data] we want associated with that type.
325
//!
326
//! For example, we can register [`ReflectDefault`] on our type so that its `Default` implementation
327
//! may be used dynamically.
328
//!
329
//! ```
330
//! # use bevy_reflect::{Reflect, TypeRegistry, prelude::ReflectDefault};
331
//! #[derive(Reflect, Default)]
332
//! struct MyStruct {
333
//! foo: i32
334
//! }
335
//! let mut registry = TypeRegistry::empty();
336
//! registry.register::<MyStruct>();
337
//! registry.register_type_data::<MyStruct, ReflectDefault>();
338
//!
339
//! let registration = registry.get(core::any::TypeId::of::<MyStruct>()).unwrap();
340
//! let reflect_default = registration.data::<ReflectDefault>().unwrap();
341
//!
342
//! let new_value: Box<dyn Reflect> = reflect_default.default();
343
//! assert!(new_value.is::<MyStruct>());
344
//! ```
345
//!
346
//! Because this operation is so common, the derive macro actually has a shorthand for it.
347
//! By using the `#[reflect(Trait)]` attribute, the derive macro will automatically register a matching,
348
//! in-scope `ReflectTrait` type within the `GetTypeRegistration` implementation.
349
//!
350
//! ```
351
//! use bevy_reflect::prelude::{Reflect, ReflectDefault};
352
//!
353
//! #[derive(Reflect, Default)]
354
//! #[reflect(Default)]
355
//! struct MyStruct {
356
//! foo: i32
357
//! }
358
//! ```
359
//!
360
//! ## Reflecting Traits
361
//!
362
//! Type data doesn't have to be tied to a trait, but it's often extremely useful to create trait type data.
363
//! These allow traits to be used directly on a `dyn Reflect` (and not a `dyn PartialReflect`)
364
//! while utilizing the underlying type's implementation.
365
//!
366
//! For any [object-safe] trait, we can easily generate a corresponding `ReflectTrait` type for our trait
367
//! using the [`#[reflect_trait]`](reflect_trait) macro.
368
//!
369
//! ```
370
//! # use bevy_reflect::{Reflect, reflect_trait, TypeRegistry};
371
//! #[reflect_trait] // Generates a `ReflectMyTrait` type
372
//! pub trait MyTrait {}
373
//! impl<T: Reflect> MyTrait for T {}
374
//!
375
//! let mut registry = TypeRegistry::new();
376
//! registry.register_type_data::<i32, ReflectMyTrait>();
377
//! ```
378
//!
379
//! The generated type data can be used to convert a valid `dyn Reflect` into a `dyn MyTrait`.
380
//! See the [dynamic types example](https://github.com/bevyengine/bevy/blob/latest/examples/reflection/dynamic_types.rs)
381
//! for more information and usage details.
382
//!
383
//! # Serialization
384
//!
385
//! By using reflection, we are also able to get serialization capabilities for free.
386
//! In fact, using [`bevy_reflect`] can result in faster compile times and reduced code generation over
387
//! directly deriving the [`serde`] traits.
388
//!
389
//! The way it works is by moving the serialization logic into common serializers and deserializers:
390
//! * [`ReflectSerializer`]
391
//! * [`TypedReflectSerializer`]
392
//! * [`ReflectDeserializer`]
393
//! * [`TypedReflectDeserializer`]
394
//!
395
//! All of these structs require a reference to the [registry] so that [type information] can be retrieved,
396
//! as well as registered type data, such as [`ReflectSerialize`] and [`ReflectDeserialize`].
397
//!
398
//! The general entry point are the "untyped" versions of these structs.
399
//! These will automatically extract the type information and pass them into their respective "typed" version.
400
//!
401
//! The output of the `ReflectSerializer` will be a map, where the key is the [type path]
402
//! and the value is the serialized data.
403
//! The `TypedReflectSerializer` will simply output the serialized data.
404
//!
405
//! The `ReflectDeserializer` can be used to deserialize this map and return a `Box<dyn Reflect>`,
406
//! where the underlying type will be a dynamic type representing some concrete type (except for opaque types).
407
//!
408
//! Again, it's important to remember that dynamic types may need to be converted to their concrete counterparts
409
//! in order to be used in certain cases.
410
//! This can be achieved using [`FromReflect`].
411
//!
412
//! ```
413
//! # use serde::de::DeserializeSeed;
414
//! # use bevy_reflect::{
415
//! # serde::{ReflectSerializer, ReflectDeserializer},
416
//! # Reflect, PartialReflect, FromReflect, TypeRegistry
417
//! # };
418
//! #[derive(Reflect, PartialEq, Debug)]
419
//! struct MyStruct {
420
//! foo: i32
421
//! }
422
//!
423
//! let original_value = MyStruct {
424
//! foo: 123
425
//! };
426
//!
427
//! // Register
428
//! let mut registry = TypeRegistry::new();
429
//! registry.register::<MyStruct>();
430
//!
431
//! // Serialize
432
//! let reflect_serializer = ReflectSerializer::new(original_value.as_partial_reflect(), &registry);
433
//! let serialized_value: String = ron::to_string(&reflect_serializer).unwrap();
434
//!
435
//! // Deserialize
436
//! let reflect_deserializer = ReflectDeserializer::new(&registry);
437
//! let deserialized_value: Box<dyn PartialReflect> = reflect_deserializer.deserialize(
438
//! &mut ron::Deserializer::from_str(&serialized_value).unwrap()
439
//! ).unwrap();
440
//!
441
//! // Convert
442
//! let converted_value = <MyStruct as FromReflect>::from_reflect(&*deserialized_value).unwrap();
443
//!
444
//! assert_eq!(original_value, converted_value);
445
//! ```
446
//!
447
//! # Limitations
448
//!
449
//! While this crate offers a lot in terms of adding reflection to Rust,
450
//! it does come with some limitations that don't make it as featureful as reflection
451
//! in other programming languages.
452
//!
453
//! ## Non-Static Lifetimes
454
//!
455
//! One of the most obvious limitations is the `'static` requirement.
456
//! Rust requires fields to define a lifetime for referenced data,
457
//! but [`Reflect`] requires all types to have a `'static` lifetime.
458
//! This makes it impossible to reflect any type with non-static borrowed data.
459
//!
460
//! ## Generic Function Reflection
461
//!
462
//! Another limitation is the inability to reflect over generic functions directly. It can be done, but will
463
//! typically require manual monomorphization (i.e. manually specifying the types the generic method can
464
//! take).
465
//!
466
//! # Features
467
//!
468
//! ## `bevy`
469
//!
470
//! | Default | Dependencies |
471
//! | :-----: | :---------------------------------------: |
472
//! | ❌ | [`bevy_math`], [`glam`], [`smallvec`] |
473
//!
474
//! This feature makes it so that the appropriate reflection traits are implemented on all the types
475
//! necessary for the [Bevy] game engine.
476
//! enables the optional dependencies: [`bevy_math`], [`glam`], and [`smallvec`].
477
//! These dependencies are used by the [Bevy] game engine and must define their reflection implementations
478
//! within this crate due to Rust's [orphan rule].
479
//!
480
//! ## `functions`
481
//!
482
//! | Default | Dependencies |
483
//! | :-----: | :-------------------------------: |
484
//! | ❌ | [`bevy_reflect_derive/functions`] |
485
//!
486
//! This feature allows creating a [`DynamicFunction`] or [`DynamicFunctionMut`] from Rust functions. Dynamic
487
//! functions can then be called with valid [`ArgList`]s.
488
//!
489
//! For more information, read the [`func`] module docs.
490
//!
491
//! ## `documentation`
492
//!
493
//! | Default | Dependencies |
494
//! | :-----: | :-------------------------------------------: |
495
//! | ❌ | [`bevy_reflect_derive/documentation`] |
496
//!
497
//! This feature enables capturing doc comments as strings for items that [derive `Reflect`].
498
//! Documentation information can then be accessed at runtime on the [`TypeInfo`] of that item.
499
//!
500
//! This can be useful for generating documentation for scripting language interop or
501
//! for displaying tooltips in an editor.
502
//!
503
//! ## `debug`
504
//!
505
//! | Default | Dependencies |
506
//! | :-----: | :-------------------------------------------: |
507
//! | ✅ | `debug_stack` |
508
//!
509
//! This feature enables useful debug features for reflection.
510
//!
511
//! This includes the `debug_stack` feature,
512
//! which enables capturing the type stack when serializing or deserializing a type
513
//! and displaying it in error messages.
514
//!
515
//! ## `auto_register_inventory`/`auto_register_static`
516
//!
517
//! | Default | Dependencies |
518
//! | :-----: | :-------------------------------: |
519
//! | ✅ | `bevy_reflect_derive/auto_register_inventory` |
520
//! | ❌ | `bevy_reflect_derive/auto_register_static` |
521
//!
522
//! These features enable automatic registration of types that derive [`Reflect`].
523
//!
524
//! - `auto_register_inventory` uses `inventory` to collect types on supported platforms (Linux, macOS, iOS, FreeBSD, Android, Windows, WebAssembly).
525
//! - `auto_register_static` uses platform-independent way to collect types, but requires additional setup and might
526
//! slow down compilation, so it should only be used on platforms not supported by `inventory`.
527
//! See documentation for [`load_type_registrations`] macro for more info
528
//!
529
//! When this feature is enabled `bevy_reflect` will automatically collects all types that derive [`Reflect`] on app startup,
530
//! and [`TypeRegistry::register_derived_types`] can be used to register these types at any point in the program.
531
//! However, this does not apply to types with generics: their desired monomorphized representations must be registered manually.
532
//!
533
//! [Reflection]: https://en.wikipedia.org/wiki/Reflective_programming
534
//! [Bevy]: https://bevy.org/
535
//! [limitations]: #limitations
536
//! [`bevy_reflect`]: crate
537
//! [introspection]: https://en.wikipedia.org/wiki/Type_introspection
538
//! [subtraits]: #the-reflection-subtraits
539
//! [the type registry]: #type-registration
540
//! [runtime cost]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#trait-objects-perform-dynamic-dispatch
541
//! [the language feature for dyn upcasting coercion]: https://github.com/rust-lang/rust/issues/65991
542
//! [derive macro]: derive@crate::Reflect
543
//! [`'static` lifetime]: https://doc.rust-lang.org/rust-by-example/scope/lifetime/static_lifetime.html#trait-bound
544
//! [`Function`]: crate::func::Function
545
//! [derive macro documentation]: derive@crate::Reflect
546
//! [deriving `Reflect`]: derive@crate::Reflect
547
//! [type data]: TypeData
548
//! [`ReflectDefault`]: std_traits::ReflectDefault
549
//! [object-safe]: https://doc.rust-lang.org/reference/items/traits.html#object-safety
550
//! [`serde`]: ::serde
551
//! [`ReflectSerializer`]: serde::ReflectSerializer
552
//! [`TypedReflectSerializer`]: serde::TypedReflectSerializer
553
//! [`ReflectDeserializer`]: serde::ReflectDeserializer
554
//! [`TypedReflectDeserializer`]: serde::TypedReflectDeserializer
555
//! [registry]: TypeRegistry
556
//! [type information]: TypeInfo
557
//! [type path]: TypePath
558
//! [type registry]: TypeRegistry
559
//! [`bevy_math`]: https://docs.rs/bevy_math/latest/bevy_math/
560
//! [`glam`]: https://docs.rs/glam/latest/glam/
561
//! [`smallvec`]: https://docs.rs/smallvec/latest/smallvec/
562
//! [orphan rule]: https://doc.rust-lang.org/book/ch10-02-traits.html#implementing-a-trait-on-a-type:~:text=But%20we%20can%E2%80%99t,implementation%20to%20use.
563
//! [`bevy_reflect_derive/documentation`]: bevy_reflect_derive
564
//! [`bevy_reflect_derive/functions`]: bevy_reflect_derive
565
//! [`DynamicFunction`]: crate::func::DynamicFunction
566
//! [`DynamicFunctionMut`]: crate::func::DynamicFunctionMut
567
//! [`ArgList`]: crate::func::ArgList
568
//! [derive `Reflect`]: derive@crate::Reflect
569
570
#![no_std]
571
572
#[cfg(feature = "std")]
573
extern crate std;
574
575
extern crate alloc;
576
577
// Required to make proc macros work in bevy itself.
578
extern crate self as bevy_reflect;
579
580
mod array;
581
mod error;
582
mod fields;
583
mod from_reflect;
584
#[cfg(feature = "functions")]
585
pub mod func;
586
mod kind;
587
mod list;
588
mod map;
589
mod path;
590
mod reflect;
591
mod reflectable;
592
mod remote;
593
mod set;
594
mod struct_trait;
595
mod tuple;
596
mod tuple_struct;
597
mod type_info;
598
mod type_path;
599
mod type_registry;
600
601
mod impls {
602
mod alloc;
603
mod bevy_platform;
604
mod core;
605
mod foldhash;
606
#[cfg(feature = "hashbrown")]
607
mod hashbrown;
608
mod macros;
609
#[cfg(feature = "std")]
610
mod std;
611
612
#[cfg(feature = "glam")]
613
mod glam;
614
#[cfg(feature = "petgraph")]
615
mod petgraph;
616
#[cfg(feature = "smallvec")]
617
mod smallvec;
618
#[cfg(feature = "smol_str")]
619
mod smol_str;
620
#[cfg(feature = "uuid")]
621
mod uuid;
622
#[cfg(feature = "wgpu-types")]
623
mod wgpu_types;
624
}
625
626
pub mod attributes;
627
mod enums;
628
mod generics;
629
pub mod serde;
630
pub mod std_traits;
631
#[cfg(feature = "debug_stack")]
632
mod type_info_stack;
633
pub mod utility;
634
635
/// The reflect prelude.
636
///
637
/// This includes the most common types in this crate, re-exported for your convenience.
638
pub mod prelude {
639
pub use crate::std_traits::*;
640
641
#[doc(hidden)]
642
pub use crate::{
643
reflect_trait, FromReflect, GetField, GetPath, GetTupleStructField, PartialReflect,
644
Reflect, ReflectDeserialize, ReflectFromReflect, ReflectPath, ReflectSerialize, Struct,
645
TupleStruct, TypePath,
646
};
647
648
#[cfg(feature = "functions")]
649
pub use crate::func::{Function, IntoFunction, IntoFunctionMut};
650
}
651
652
pub use array::*;
653
pub use enums::*;
654
pub use error::*;
655
pub use fields::*;
656
pub use from_reflect::*;
657
pub use generics::*;
658
pub use kind::*;
659
pub use list::*;
660
pub use map::*;
661
pub use path::*;
662
pub use reflect::*;
663
pub use reflectable::*;
664
pub use remote::*;
665
pub use set::*;
666
pub use struct_trait::*;
667
pub use tuple::*;
668
pub use tuple_struct::*;
669
pub use type_info::*;
670
pub use type_path::*;
671
pub use type_registry::*;
672
673
pub use bevy_reflect_derive::*;
674
pub use erased_serde;
675
676
/// Exports used by the reflection macros.
677
///
678
/// These are not meant to be used directly and are subject to breaking changes.
679
#[doc(hidden)]
680
pub mod __macro_exports {
681
use crate::{
682
DynamicArray, DynamicEnum, DynamicList, DynamicMap, DynamicStruct, DynamicTuple,
683
DynamicTupleStruct, GetTypeRegistration, TypeRegistry,
684
};
685
686
/// Re-exports of items from the [`alloc`] crate.
687
///
688
/// This is required because in `std` environments (e.g., the `std` feature is enabled)
689
/// the `alloc` crate may not have been included, making its namespace unreliable.
690
pub mod alloc_utils {
691
pub use ::alloc::{
692
borrow::{Cow, ToOwned},
693
boxed::Box,
694
string::ToString,
695
};
696
}
697
698
/// A wrapper trait around [`GetTypeRegistration`].
699
///
700
/// This trait is used by the derive macro to recursively register all type dependencies.
701
/// It's used instead of `GetTypeRegistration` directly to avoid making dynamic types also
702
/// implement `GetTypeRegistration` in order to be used as active fields.
703
///
704
/// This trait has a blanket implementation for all types that implement `GetTypeRegistration`
705
/// and manual implementations for all dynamic types (which simply do nothing).
706
#[diagnostic::on_unimplemented(
707
message = "`{Self}` does not implement `GetTypeRegistration` so cannot be registered for reflection",
708
note = "consider annotating `{Self}` with `#[derive(Reflect)]`"
709
)]
710
pub trait RegisterForReflection {
711
#[expect(
712
unused_variables,
713
reason = "The parameters here are intentionally unused by the default implementation; however, putting underscores here will result in the underscores being copied by rust-analyzer's tab completion."
714
)]
715
fn __register(registry: &mut TypeRegistry) {}
716
}
717
718
impl<T: GetTypeRegistration> RegisterForReflection for T {
719
fn __register(registry: &mut TypeRegistry) {
720
registry.register::<T>();
721
}
722
}
723
724
impl RegisterForReflection for DynamicEnum {}
725
726
impl RegisterForReflection for DynamicTupleStruct {}
727
728
impl RegisterForReflection for DynamicStruct {}
729
730
impl RegisterForReflection for DynamicMap {}
731
732
impl RegisterForReflection for DynamicList {}
733
734
impl RegisterForReflection for DynamicArray {}
735
736
impl RegisterForReflection for DynamicTuple {}
737
738
/// Automatic reflect registration implementation
739
#[cfg(feature = "auto_register")]
740
pub mod auto_register {
741
pub use super::*;
742
743
#[cfg(all(
744
not(feature = "auto_register_inventory"),
745
not(feature = "auto_register_static")
746
))]
747
compile_error!(
748
"Choosing a backend is required for automatic reflect registration. Please enable either the \"auto_register_inventory\" or the \"auto_register_static\" feature."
749
);
750
751
/// inventory impl
752
#[cfg(all(
753
not(feature = "auto_register_static"),
754
feature = "auto_register_inventory"
755
))]
756
mod __automatic_type_registration_impl {
757
use super::*;
758
759
pub use inventory;
760
761
/// Stores type registration functions
762
pub struct AutomaticReflectRegistrations(pub fn(&mut TypeRegistry));
763
764
/// Registers all collected types.
765
pub fn register_types(registry: &mut TypeRegistry) {
766
#[cfg(target_family = "wasm")]
767
wasm_support::init();
768
for registration_fn in inventory::iter::<AutomaticReflectRegistrations> {
769
registration_fn.0(registry);
770
}
771
}
772
773
inventory::collect!(AutomaticReflectRegistrations);
774
775
#[cfg(target_family = "wasm")]
776
mod wasm_support {
777
use bevy_platform::sync::atomic::{AtomicBool, Ordering};
778
779
static INIT_DONE: AtomicBool = AtomicBool::new(false);
780
781
#[expect(unsafe_code, reason = "This function is generated by linker.")]
782
unsafe extern "C" {
783
fn __wasm_call_ctors();
784
}
785
786
/// This function must be called before using [`inventory::iter`] on [`AutomaticReflectRegistrations`] to run constructors on all platforms.
787
pub fn init() {
788
if INIT_DONE.swap(true, Ordering::Relaxed) {
789
return;
790
};
791
// SAFETY:
792
// This will call constructors on wasm platforms at most once (as long as `init` is the only function that calls `__wasm_call_ctors`).
793
//
794
// For more information see: https://docs.rs/inventory/latest/inventory/#webassembly-and-constructors
795
#[expect(
796
unsafe_code,
797
reason = "This function must be called to use inventory on wasm."
798
)]
799
unsafe {
800
__wasm_call_ctors();
801
}
802
}
803
}
804
}
805
806
/// static impl
807
#[cfg(feature = "auto_register_static")]
808
mod __automatic_type_registration_impl {
809
use super::*;
810
use alloc::vec::Vec;
811
use bevy_platform::sync::Mutex;
812
813
static REGISTRATION_FNS: Mutex<Vec<fn(&mut TypeRegistry)>> = Mutex::new(Vec::new());
814
815
/// Adds adds a new registration function for [`TypeRegistry`]
816
pub fn push_registration_fn(registration_fn: fn(&mut TypeRegistry)) {
817
REGISTRATION_FNS.lock().unwrap().push(registration_fn);
818
}
819
820
/// Registers all collected types.
821
pub fn register_types(registry: &mut TypeRegistry) {
822
for func in REGISTRATION_FNS.lock().unwrap().iter() {
823
(func)(registry);
824
}
825
}
826
}
827
828
#[cfg(any(feature = "auto_register_static", feature = "auto_register_inventory"))]
829
pub use __automatic_type_registration_impl::*;
830
}
831
}
832
833
#[cfg(test)]
834
#[expect(
835
clippy::approx_constant,
836
reason = "We don't need the exact value of Pi here."
837
)]
838
mod tests {
839
use ::serde::{de::DeserializeSeed, Deserialize, Serialize};
840
use alloc::{
841
borrow::Cow,
842
boxed::Box,
843
format,
844
string::{String, ToString},
845
vec,
846
vec::Vec,
847
};
848
use bevy_platform::collections::HashMap;
849
use core::{
850
any::TypeId,
851
fmt::{Debug, Formatter},
852
hash::Hash,
853
marker::PhantomData,
854
};
855
use disqualified::ShortName;
856
use ron::{
857
ser::{to_string_pretty, PrettyConfig},
858
Deserializer,
859
};
860
use static_assertions::{assert_impl_all, assert_not_impl_all};
861
862
use super::{prelude::*, *};
863
use crate::{
864
serde::{ReflectDeserializer, ReflectSerializer},
865
utility::GenericTypePathCell,
866
};
867
868
#[test]
869
fn try_apply_should_detect_kinds() {
870
#[derive(Reflect, Debug)]
871
struct Struct {
872
a: u32,
873
b: f32,
874
}
875
876
#[derive(Reflect, Debug)]
877
enum Enum {
878
A,
879
B(u32),
880
}
881
882
let mut struct_target = Struct {
883
a: 0xDEADBEEF,
884
b: 3.14,
885
};
886
887
let mut enum_target = Enum::A;
888
889
let array_src = [8, 0, 8];
890
891
let result = struct_target.try_apply(&enum_target);
892
assert!(
893
matches!(
894
result,
895
Err(ApplyError::MismatchedKinds {
896
from_kind: ReflectKind::Enum,
897
to_kind: ReflectKind::Struct
898
})
899
),
900
"result was {result:?}"
901
);
902
903
let result = enum_target.try_apply(&array_src);
904
assert!(
905
matches!(
906
result,
907
Err(ApplyError::MismatchedKinds {
908
from_kind: ReflectKind::Array,
909
to_kind: ReflectKind::Enum
910
})
911
),
912
"result was {result:?}"
913
);
914
}
915
916
#[test]
917
fn reflect_struct() {
918
#[derive(Reflect)]
919
struct Foo {
920
a: u32,
921
b: f32,
922
c: Bar,
923
}
924
#[derive(Reflect)]
925
struct Bar {
926
x: u32,
927
}
928
929
let mut foo = Foo {
930
a: 42,
931
b: 3.14,
932
c: Bar { x: 1 },
933
};
934
935
let a = *foo.get_field::<u32>("a").unwrap();
936
assert_eq!(a, 42);
937
938
*foo.get_field_mut::<u32>("a").unwrap() += 1;
939
assert_eq!(foo.a, 43);
940
941
let bar = foo.get_field::<Bar>("c").unwrap();
942
assert_eq!(bar.x, 1);
943
944
// nested retrieval
945
let c = foo.field("c").unwrap();
946
let value = c.reflect_ref().as_struct().unwrap();
947
assert_eq!(*value.get_field::<u32>("x").unwrap(), 1);
948
949
// patch Foo with a dynamic struct
950
let mut dynamic_struct = DynamicStruct::default();
951
dynamic_struct.insert("a", 123u32);
952
dynamic_struct.insert("should_be_ignored", 456);
953
954
foo.apply(&dynamic_struct);
955
assert_eq!(foo.a, 123);
956
}
957
958
#[test]
959
fn reflect_map() {
960
#[derive(Reflect, Hash)]
961
#[reflect(Hash)]
962
struct Foo {
963
a: u32,
964
b: String,
965
}
966
967
let key_a = Foo {
968
a: 1,
969
b: "k1".to_string(),
970
};
971
972
let key_b = Foo {
973
a: 1,
974
b: "k1".to_string(),
975
};
976
977
let key_c = Foo {
978
a: 3,
979
b: "k3".to_string(),
980
};
981
982
let mut map = DynamicMap::default();
983
map.insert(key_a, 10u32);
984
assert_eq!(
985
10,
986
*map.get(&key_b).unwrap().try_downcast_ref::<u32>().unwrap()
987
);
988
assert!(map.get(&key_c).is_none());
989
*map.get_mut(&key_b)
990
.unwrap()
991
.try_downcast_mut::<u32>()
992
.unwrap() = 20;
993
assert_eq!(
994
20,
995
*map.get(&key_b).unwrap().try_downcast_ref::<u32>().unwrap()
996
);
997
}
998
999
#[test]
1000
fn reflect_unit_struct() {
1001
#[derive(Reflect)]
1002
struct Foo(u32, u64);
1003
1004
let mut foo = Foo(1, 2);
1005
assert_eq!(1, *foo.get_field::<u32>(0).unwrap());
1006
assert_eq!(2, *foo.get_field::<u64>(1).unwrap());
1007
1008
let mut patch = DynamicTupleStruct::default();
1009
patch.insert(3u32);
1010
patch.insert(4u64);
1011
assert_eq!(
1012
3,
1013
*patch.field(0).unwrap().try_downcast_ref::<u32>().unwrap()
1014
);
1015
assert_eq!(
1016
4,
1017
*patch.field(1).unwrap().try_downcast_ref::<u64>().unwrap()
1018
);
1019
1020
foo.apply(&patch);
1021
assert_eq!(3, foo.0);
1022
assert_eq!(4, foo.1);
1023
1024
let mut iter = patch.iter_fields();
1025
assert_eq!(3, *iter.next().unwrap().try_downcast_ref::<u32>().unwrap());
1026
assert_eq!(4, *iter.next().unwrap().try_downcast_ref::<u64>().unwrap());
1027
}
1028
1029
#[test]
1030
#[should_panic(
1031
expected = "the given key of type `bevy_reflect::tests::Foo` does not support hashing"
1032
)]
1033
fn reflect_map_no_hash() {
1034
#[derive(Reflect)]
1035
struct Foo {
1036
a: u32,
1037
}
1038
1039
let foo = Foo { a: 1 };
1040
assert!(foo.reflect_hash().is_none());
1041
1042
let mut map = DynamicMap::default();
1043
map.insert(foo, 10u32);
1044
}
1045
1046
#[test]
1047
#[should_panic(
1048
expected = "the dynamic type `bevy_reflect::DynamicStruct` (representing `bevy_reflect::tests::Foo`) does not support hashing"
1049
)]
1050
fn reflect_map_no_hash_dynamic_representing() {
1051
#[derive(Reflect, Hash)]
1052
#[reflect(Hash)]
1053
struct Foo {
1054
a: u32,
1055
}
1056
1057
let foo = Foo { a: 1 };
1058
assert!(foo.reflect_hash().is_some());
1059
let dynamic = foo.to_dynamic_struct();
1060
1061
let mut map = DynamicMap::default();
1062
map.insert(dynamic, 11u32);
1063
}
1064
1065
#[test]
1066
#[should_panic(
1067
expected = "the dynamic type `bevy_reflect::DynamicStruct` does not support hashing"
1068
)]
1069
fn reflect_map_no_hash_dynamic() {
1070
#[derive(Reflect, Hash)]
1071
#[reflect(Hash)]
1072
struct Foo {
1073
a: u32,
1074
}
1075
1076
let mut dynamic = DynamicStruct::default();
1077
dynamic.insert("a", 4u32);
1078
assert!(dynamic.reflect_hash().is_none());
1079
1080
let mut map = DynamicMap::default();
1081
map.insert(dynamic, 11u32);
1082
}
1083
1084
#[test]
1085
fn reflect_ignore() {
1086
#[derive(Reflect)]
1087
struct Foo {
1088
a: u32,
1089
#[reflect(ignore)]
1090
_b: u32,
1091
}
1092
1093
let foo = Foo { a: 1, _b: 2 };
1094
1095
let values: Vec<u32> = foo
1096
.iter_fields()
1097
.map(|value| *value.try_downcast_ref::<u32>().unwrap())
1098
.collect();
1099
assert_eq!(values, vec![1]);
1100
}
1101
1102
/// This test ensures that we are able to reflect generic types with one or more type parameters.
1103
///
1104
/// When there is an `Add` implementation for `String`, the compiler isn't able to infer the correct
1105
/// type to deref to.
1106
/// If we don't append the strings in the `TypePath` derive correctly (i.e. explicitly specifying the type),
1107
/// we'll get a compilation error saying that "`&String` cannot be added to `String`".
1108
///
1109
/// So this test just ensures that we do that correctly.
1110
///
1111
/// This problem is a known issue and is unexpectedly expected behavior:
1112
/// - <https://github.com/rust-lang/rust/issues/77143>
1113
/// - <https://github.com/bodil/smartstring/issues/7>
1114
/// - <https://github.com/pola-rs/polars/issues/14666>
1115
#[test]
1116
fn should_reflect_generic() {
1117
struct FakeString {}
1118
1119
// This implementation confuses the compiler when trying to add a `&String` to a `String`
1120
impl core::ops::Add<FakeString> for String {
1121
type Output = Self;
1122
fn add(self, _rhs: FakeString) -> Self::Output {
1123
unreachable!()
1124
}
1125
}
1126
1127
#[derive(Reflect)]
1128
struct Foo<A>(A);
1129
1130
#[derive(Reflect)]
1131
struct Bar<A, B>(A, B);
1132
1133
#[derive(Reflect)]
1134
struct Baz<A, B, C>(A, B, C);
1135
}
1136
1137
#[test]
1138
fn should_reflect_clone() {
1139
// Struct
1140
#[derive(Reflect, Debug, PartialEq)]
1141
struct Foo(usize);
1142
1143
let value = Foo(123);
1144
let clone = value.reflect_clone().expect("should reflect_clone struct");
1145
assert_eq!(value, clone.take::<Foo>().unwrap());
1146
1147
// Tuple
1148
let foo = (123, 4.56);
1149
let clone = foo.reflect_clone().expect("should reflect_clone tuple");
1150
assert_eq!(foo, clone.take::<(u32, f32)>().unwrap());
1151
}
1152
1153
#[test]
1154
fn should_reflect_clone_generic_type() {
1155
#[derive(Reflect, Debug, PartialEq)]
1156
struct Foo<T, U>(T, #[reflect(ignore, clone)] PhantomData<U>);
1157
#[derive(TypePath, Debug, PartialEq)]
1158
struct Bar;
1159
1160
// `usize` will be cloned via `Reflect::reflect_clone`
1161
// `PhantomData<Bar>` will be cloned via `Clone::clone`
1162
let value = Foo::<usize, Bar>(123, PhantomData);
1163
let clone = value
1164
.reflect_clone()
1165
.expect("should reflect_clone generic struct");
1166
assert_eq!(value, clone.take::<Foo<usize, Bar>>().unwrap());
1167
}
1168
1169
#[test]
1170
fn should_reflect_clone_with_clone() {
1171
// A custom clone function to verify that the `#[reflect(Clone)]` container attribute
1172
// takes precedence over the `#[reflect(clone)]` field attribute.
1173
#[expect(
1174
dead_code,
1175
reason = "if things are working correctly, this function should never be called"
1176
)]
1177
fn custom_clone(_value: &usize) -> usize {
1178
panic!("should not be called");
1179
}
1180
1181
// Tuple Struct
1182
#[derive(Reflect, Clone, Debug, PartialEq)]
1183
#[reflect(Clone)]
1184
struct Foo(#[reflect(clone = "custom_clone")] usize);
1185
1186
let value = Foo(123);
1187
let clone = value
1188
.reflect_clone()
1189
.expect("should reflect_clone tuple struct");
1190
assert_eq!(value, clone.take::<Foo>().unwrap());
1191
1192
// Struct
1193
#[derive(Reflect, Clone, Debug, PartialEq)]
1194
#[reflect(Clone)]
1195
struct Bar {
1196
#[reflect(clone = "custom_clone")]
1197
value: usize,
1198
}
1199
1200
let value = Bar { value: 123 };
1201
let clone = value.reflect_clone().expect("should reflect_clone struct");
1202
assert_eq!(value, clone.take::<Bar>().unwrap());
1203
1204
// Enum
1205
#[derive(Reflect, Clone, Debug, PartialEq)]
1206
#[reflect(Clone)]
1207
enum Baz {
1208
Unit,
1209
Tuple(#[reflect(clone = "custom_clone")] usize),
1210
Struct {
1211
#[reflect(clone = "custom_clone")]
1212
value: usize,
1213
},
1214
}
1215
1216
let value = Baz::Unit;
1217
let clone = value
1218
.reflect_clone()
1219
.expect("should reflect_clone unit variant");
1220
assert_eq!(value, clone.take::<Baz>().unwrap());
1221
1222
let value = Baz::Tuple(123);
1223
let clone = value
1224
.reflect_clone()
1225
.expect("should reflect_clone tuple variant");
1226
assert_eq!(value, clone.take::<Baz>().unwrap());
1227
1228
let value = Baz::Struct { value: 123 };
1229
let clone = value
1230
.reflect_clone()
1231
.expect("should reflect_clone struct variant");
1232
assert_eq!(value, clone.take::<Baz>().unwrap());
1233
}
1234
1235
#[test]
1236
fn should_custom_reflect_clone() {
1237
#[derive(Reflect, Debug, PartialEq)]
1238
#[reflect(Clone(clone_foo))]
1239
struct Foo(usize);
1240
1241
fn clone_foo(foo: &Foo) -> Foo {
1242
Foo(foo.0 + 198)
1243
}
1244
1245
let foo = Foo(123);
1246
let clone = foo.reflect_clone().unwrap();
1247
assert_eq!(Foo(321), clone.take::<Foo>().unwrap());
1248
}
1249
1250
#[test]
1251
fn should_not_clone_ignored_fields() {
1252
// Tuple Struct
1253
#[derive(Reflect, Clone, Debug, PartialEq)]
1254
struct Foo(#[reflect(ignore)] usize);
1255
1256
let foo = Foo(123);
1257
let clone = foo.reflect_clone();
1258
assert_eq!(
1259
clone.unwrap_err(),
1260
ReflectCloneError::FieldNotCloneable {
1261
field: FieldId::Unnamed(0),
1262
variant: None,
1263
container_type_path: Cow::Borrowed(Foo::type_path()),
1264
}
1265
);
1266
1267
// Struct
1268
#[derive(Reflect, Clone, Debug, PartialEq)]
1269
struct Bar {
1270
#[reflect(ignore)]
1271
value: usize,
1272
}
1273
1274
let bar = Bar { value: 123 };
1275
let clone = bar.reflect_clone();
1276
assert_eq!(
1277
clone.unwrap_err(),
1278
ReflectCloneError::FieldNotCloneable {
1279
field: FieldId::Named(Cow::Borrowed("value")),
1280
variant: None,
1281
container_type_path: Cow::Borrowed(Bar::type_path()),
1282
}
1283
);
1284
1285
// Enum
1286
#[derive(Reflect, Clone, Debug, PartialEq)]
1287
enum Baz {
1288
Tuple(#[reflect(ignore)] usize),
1289
Struct {
1290
#[reflect(ignore)]
1291
value: usize,
1292
},
1293
}
1294
1295
let baz = Baz::Tuple(123);
1296
let clone = baz.reflect_clone();
1297
assert_eq!(
1298
clone.unwrap_err(),
1299
ReflectCloneError::FieldNotCloneable {
1300
field: FieldId::Unnamed(0),
1301
variant: Some(Cow::Borrowed("Tuple")),
1302
container_type_path: Cow::Borrowed(Baz::type_path()),
1303
}
1304
);
1305
1306
let baz = Baz::Struct { value: 123 };
1307
let clone = baz.reflect_clone();
1308
assert_eq!(
1309
clone.unwrap_err(),
1310
ReflectCloneError::FieldNotCloneable {
1311
field: FieldId::Named(Cow::Borrowed("value")),
1312
variant: Some(Cow::Borrowed("Struct")),
1313
container_type_path: Cow::Borrowed(Baz::type_path()),
1314
}
1315
);
1316
}
1317
1318
#[test]
1319
fn should_clone_ignored_fields_with_clone_attributes() {
1320
#[derive(Reflect, Clone, Debug, PartialEq)]
1321
struct Foo(#[reflect(ignore, clone)] usize);
1322
1323
let foo = Foo(123);
1324
let clone = foo.reflect_clone().unwrap();
1325
assert_eq!(Foo(123), clone.take::<Foo>().unwrap());
1326
1327
#[derive(Reflect, Clone, Debug, PartialEq)]
1328
struct Bar(#[reflect(ignore, clone = "clone_usize")] usize);
1329
1330
fn clone_usize(this: &usize) -> usize {
1331
*this + 198
1332
}
1333
1334
let bar = Bar(123);
1335
let clone = bar.reflect_clone().unwrap();
1336
assert_eq!(Bar(321), clone.take::<Bar>().unwrap());
1337
}
1338
1339
#[test]
1340
fn should_composite_reflect_clone() {
1341
#[derive(Reflect, Debug, PartialEq)]
1342
enum MyEnum {
1343
Unit,
1344
Tuple(
1345
Foo,
1346
#[reflect(ignore, clone)] Bar,
1347
#[reflect(clone = "clone_baz")] Baz,
1348
),
1349
Struct {
1350
foo: Foo,
1351
#[reflect(ignore, clone)]
1352
bar: Bar,
1353
#[reflect(clone = "clone_baz")]
1354
baz: Baz,
1355
},
1356
}
1357
1358
#[derive(Reflect, Debug, PartialEq)]
1359
struct Foo {
1360
#[reflect(clone = "clone_bar")]
1361
bar: Bar,
1362
baz: Baz,
1363
}
1364
1365
#[derive(Reflect, Default, Clone, Debug, PartialEq)]
1366
#[reflect(Clone)]
1367
struct Bar(String);
1368
1369
#[derive(Reflect, Debug, PartialEq)]
1370
struct Baz(String);
1371
1372
fn clone_bar(bar: &Bar) -> Bar {
1373
Bar(format!("{}!", bar.0))
1374
}
1375
1376
fn clone_baz(baz: &Baz) -> Baz {
1377
Baz(format!("{}!", baz.0))
1378
}
1379
1380
let my_enum = MyEnum::Unit;
1381
let clone = my_enum.reflect_clone().unwrap();
1382
assert_eq!(MyEnum::Unit, clone.take::<MyEnum>().unwrap());
1383
1384
let my_enum = MyEnum::Tuple(
1385
Foo {
1386
bar: Bar("bar".to_string()),
1387
baz: Baz("baz".to_string()),
1388
},
1389
Bar("bar".to_string()),
1390
Baz("baz".to_string()),
1391
);
1392
let clone = my_enum.reflect_clone().unwrap();
1393
assert_eq!(
1394
MyEnum::Tuple(
1395
Foo {
1396
bar: Bar("bar!".to_string()),
1397
baz: Baz("baz".to_string()),
1398
},
1399
Bar("bar".to_string()),
1400
Baz("baz!".to_string()),
1401
),
1402
clone.take::<MyEnum>().unwrap()
1403
);
1404
1405
let my_enum = MyEnum::Struct {
1406
foo: Foo {
1407
bar: Bar("bar".to_string()),
1408
baz: Baz("baz".to_string()),
1409
},
1410
bar: Bar("bar".to_string()),
1411
baz: Baz("baz".to_string()),
1412
};
1413
let clone = my_enum.reflect_clone().unwrap();
1414
assert_eq!(
1415
MyEnum::Struct {
1416
foo: Foo {
1417
bar: Bar("bar!".to_string()),
1418
baz: Baz("baz".to_string()),
1419
},
1420
bar: Bar("bar".to_string()),
1421
baz: Baz("baz!".to_string()),
1422
},
1423
clone.take::<MyEnum>().unwrap()
1424
);
1425
}
1426
1427
#[test]
1428
fn should_call_from_reflect_dynamically() {
1429
#[derive(Reflect)]
1430
struct MyStruct {
1431
foo: usize,
1432
}
1433
1434
// Register
1435
let mut registry = TypeRegistry::default();
1436
registry.register::<MyStruct>();
1437
1438
// Get type data
1439
let type_id = TypeId::of::<MyStruct>();
1440
let rfr = registry
1441
.get_type_data::<ReflectFromReflect>(type_id)
1442
.expect("the FromReflect trait should be registered");
1443
1444
// Call from_reflect
1445
let mut dynamic_struct = DynamicStruct::default();
1446
dynamic_struct.insert("foo", 123usize);
1447
let reflected = rfr
1448
.from_reflect(&dynamic_struct)
1449
.expect("the type should be properly reflected");
1450
1451
// Assert
1452
let expected = MyStruct { foo: 123 };
1453
assert!(expected
1454
.reflect_partial_eq(reflected.as_partial_reflect())
1455
.unwrap_or_default());
1456
let not_expected = MyStruct { foo: 321 };
1457
assert!(!not_expected
1458
.reflect_partial_eq(reflected.as_partial_reflect())
1459
.unwrap_or_default());
1460
}
1461
1462
#[test]
1463
fn from_reflect_should_allow_ignored_unnamed_fields() {
1464
#[derive(Reflect, Eq, PartialEq, Debug)]
1465
struct MyTupleStruct(i8, #[reflect(ignore)] i16, i32);
1466
1467
let expected = MyTupleStruct(1, 0, 3);
1468
1469
let mut dyn_tuple_struct = DynamicTupleStruct::default();
1470
dyn_tuple_struct.insert(1_i8);
1471
dyn_tuple_struct.insert(3_i32);
1472
let my_tuple_struct = <MyTupleStruct as FromReflect>::from_reflect(&dyn_tuple_struct);
1473
1474
assert_eq!(Some(expected), my_tuple_struct);
1475
1476
#[derive(Reflect, Eq, PartialEq, Debug)]
1477
enum MyEnum {
1478
Tuple(i8, #[reflect(ignore)] i16, i32),
1479
}
1480
1481
let expected = MyEnum::Tuple(1, 0, 3);
1482
1483
let mut dyn_tuple = DynamicTuple::default();
1484
dyn_tuple.insert(1_i8);
1485
dyn_tuple.insert(3_i32);
1486
1487
let mut dyn_enum = DynamicEnum::default();
1488
dyn_enum.set_variant("Tuple", dyn_tuple);
1489
1490
let my_enum = <MyEnum as FromReflect>::from_reflect(&dyn_enum);
1491
1492
assert_eq!(Some(expected), my_enum);
1493
}
1494
1495
#[test]
1496
fn from_reflect_should_use_default_field_attributes() {
1497
#[derive(Reflect, Eq, PartialEq, Debug)]
1498
struct MyStruct {
1499
// Use `Default::default()`
1500
// Note that this isn't an ignored field
1501
#[reflect(default)]
1502
foo: String,
1503
1504
// Use `get_bar_default()`
1505
#[reflect(ignore)]
1506
#[reflect(default = "get_bar_default")]
1507
bar: NotReflect,
1508
1509
// Ensure attributes can be combined
1510
#[reflect(ignore, default = "get_bar_default")]
1511
baz: NotReflect,
1512
}
1513
1514
#[derive(Eq, PartialEq, Debug)]
1515
struct NotReflect(usize);
1516
1517
fn get_bar_default() -> NotReflect {
1518
NotReflect(123)
1519
}
1520
1521
let expected = MyStruct {
1522
foo: String::default(),
1523
bar: NotReflect(123),
1524
baz: NotReflect(123),
1525
};
1526
1527
let dyn_struct = DynamicStruct::default();
1528
let my_struct = <MyStruct as FromReflect>::from_reflect(&dyn_struct);
1529
1530
assert_eq!(Some(expected), my_struct);
1531
}
1532
1533
#[test]
1534
fn from_reflect_should_use_default_variant_field_attributes() {
1535
#[derive(Reflect, Eq, PartialEq, Debug)]
1536
enum MyEnum {
1537
Foo(#[reflect(default)] String),
1538
Bar {
1539
#[reflect(default = "get_baz_default")]
1540
#[reflect(ignore)]
1541
baz: usize,
1542
},
1543
}
1544
1545
fn get_baz_default() -> usize {
1546
123
1547
}
1548
1549
let expected = MyEnum::Foo(String::default());
1550
1551
let dyn_enum = DynamicEnum::new("Foo", DynamicTuple::default());
1552
let my_enum = <MyEnum as FromReflect>::from_reflect(&dyn_enum);
1553
1554
assert_eq!(Some(expected), my_enum);
1555
1556
let expected = MyEnum::Bar {
1557
baz: get_baz_default(),
1558
};
1559
1560
let dyn_enum = DynamicEnum::new("Bar", DynamicStruct::default());
1561
let my_enum = <MyEnum as FromReflect>::from_reflect(&dyn_enum);
1562
1563
assert_eq!(Some(expected), my_enum);
1564
}
1565
1566
#[test]
1567
fn from_reflect_should_use_default_container_attribute() {
1568
#[derive(Reflect, Eq, PartialEq, Debug)]
1569
#[reflect(Default)]
1570
struct MyStruct {
1571
foo: String,
1572
#[reflect(ignore)]
1573
bar: usize,
1574
}
1575
1576
impl Default for MyStruct {
1577
fn default() -> Self {
1578
Self {
1579
foo: String::from("Hello"),
1580
bar: 123,
1581
}
1582
}
1583
}
1584
1585
let expected = MyStruct {
1586
foo: String::from("Hello"),
1587
bar: 123,
1588
};
1589
1590
let dyn_struct = DynamicStruct::default();
1591
let my_struct = <MyStruct as FromReflect>::from_reflect(&dyn_struct);
1592
1593
assert_eq!(Some(expected), my_struct);
1594
}
1595
1596
#[test]
1597
fn reflect_complex_patch() {
1598
#[derive(Reflect, Eq, PartialEq, Debug)]
1599
#[reflect(PartialEq)]
1600
struct Foo {
1601
a: u32,
1602
#[reflect(ignore)]
1603
_b: u32,
1604
c: Vec<isize>,
1605
d: HashMap<usize, i8>,
1606
e: Bar,
1607
f: (i32, Vec<isize>, Bar),
1608
g: Vec<(Baz, HashMap<usize, Bar>)>,
1609
h: [u32; 2],
1610
}
1611
1612
#[derive(Reflect, Eq, PartialEq, Clone, Debug)]
1613
#[reflect(PartialEq)]
1614
struct Bar {
1615
x: u32,
1616
}
1617
1618
#[derive(Reflect, Eq, PartialEq, Debug)]
1619
struct Baz(String);
1620
1621
let mut hash_map = <HashMap<_, _>>::default();
1622
hash_map.insert(1, 1);
1623
hash_map.insert(2, 2);
1624
1625
let mut hash_map_baz = <HashMap<_, _>>::default();
1626
hash_map_baz.insert(1, Bar { x: 0 });
1627
1628
let mut foo = Foo {
1629
a: 1,
1630
_b: 1,
1631
c: vec![1, 2],
1632
d: hash_map,
1633
e: Bar { x: 1 },
1634
f: (1, vec![1, 2], Bar { x: 1 }),
1635
g: vec![(Baz("string".to_string()), hash_map_baz)],
1636
h: [2; 2],
1637
};
1638
1639
let mut foo_patch = DynamicStruct::default();
1640
foo_patch.insert("a", 2u32);
1641
foo_patch.insert("b", 2u32); // this should be ignored
1642
1643
let mut list = DynamicList::default();
1644
list.push(3isize);
1645
list.push(4isize);
1646
list.push(5isize);
1647
foo_patch.insert("c", list.to_dynamic_list());
1648
1649
let mut map = DynamicMap::default();
1650
map.insert(2usize, 3i8);
1651
map.insert(3usize, 4i8);
1652
foo_patch.insert("d", map);
1653
1654
let mut bar_patch = DynamicStruct::default();
1655
bar_patch.insert("x", 2u32);
1656
foo_patch.insert("e", bar_patch.to_dynamic_struct());
1657
1658
let mut tuple = DynamicTuple::default();
1659
tuple.insert(2i32);
1660
tuple.insert(list);
1661
tuple.insert(bar_patch);
1662
foo_patch.insert("f", tuple);
1663
1664
let mut composite = DynamicList::default();
1665
composite.push({
1666
let mut tuple = DynamicTuple::default();
1667
tuple.insert({
1668
let mut tuple_struct = DynamicTupleStruct::default();
1669
tuple_struct.insert("new_string".to_string());
1670
tuple_struct
1671
});
1672
tuple.insert({
1673
let mut map = DynamicMap::default();
1674
map.insert(1usize, {
1675
let mut struct_ = DynamicStruct::default();
1676
struct_.insert("x", 7u32);
1677
struct_
1678
});
1679
map
1680
});
1681
tuple
1682
});
1683
foo_patch.insert("g", composite);
1684
1685
let array = DynamicArray::from_iter([2u32, 2u32]);
1686
foo_patch.insert("h", array);
1687
1688
foo.apply(&foo_patch);
1689
1690
let mut hash_map = <HashMap<_, _>>::default();
1691
hash_map.insert(2, 3);
1692
hash_map.insert(3, 4);
1693
1694
let mut hash_map_baz = <HashMap<_, _>>::default();
1695
hash_map_baz.insert(1, Bar { x: 7 });
1696
1697
let expected_foo = Foo {
1698
a: 2,
1699
_b: 1,
1700
c: vec![3, 4, 5],
1701
d: hash_map,
1702
e: Bar { x: 2 },
1703
f: (2, vec![3, 4, 5], Bar { x: 2 }),
1704
g: vec![(Baz("new_string".to_string()), hash_map_baz.clone())],
1705
h: [2; 2],
1706
};
1707
1708
assert_eq!(foo, expected_foo);
1709
1710
let new_foo = Foo::from_reflect(&foo_patch)
1711
.expect("error while creating a concrete type from a dynamic type");
1712
1713
let mut hash_map = <HashMap<_, _>>::default();
1714
hash_map.insert(2, 3);
1715
hash_map.insert(3, 4);
1716
1717
let expected_new_foo = Foo {
1718
a: 2,
1719
_b: 0,
1720
c: vec![3, 4, 5],
1721
d: hash_map,
1722
e: Bar { x: 2 },
1723
f: (2, vec![3, 4, 5], Bar { x: 2 }),
1724
g: vec![(Baz("new_string".to_string()), hash_map_baz)],
1725
h: [2; 2],
1726
};
1727
1728
assert_eq!(new_foo, expected_new_foo);
1729
}
1730
1731
#[test]
1732
fn should_auto_register_fields() {
1733
#[derive(Reflect)]
1734
struct Foo {
1735
bar: Bar,
1736
}
1737
1738
#[derive(Reflect)]
1739
enum Bar {
1740
Variant(Baz),
1741
}
1742
1743
#[derive(Reflect)]
1744
struct Baz(usize);
1745
1746
// === Basic === //
1747
let mut registry = TypeRegistry::empty();
1748
registry.register::<Foo>();
1749
1750
assert!(
1751
registry.contains(TypeId::of::<Bar>()),
1752
"registry should contain auto-registered `Bar` from `Foo`"
1753
);
1754
1755
// === Option === //
1756
let mut registry = TypeRegistry::empty();
1757
registry.register::<Option<Foo>>();
1758
1759
assert!(
1760
registry.contains(TypeId::of::<Bar>()),
1761
"registry should contain auto-registered `Bar` from `Option<Foo>`"
1762
);
1763
1764
// === Tuple === //
1765
let mut registry = TypeRegistry::empty();
1766
registry.register::<(Foo, Foo)>();
1767
1768
assert!(
1769
registry.contains(TypeId::of::<Bar>()),
1770
"registry should contain auto-registered `Bar` from `(Foo, Foo)`"
1771
);
1772
1773
// === Array === //
1774
let mut registry = TypeRegistry::empty();
1775
registry.register::<[Foo; 3]>();
1776
1777
assert!(
1778
registry.contains(TypeId::of::<Bar>()),
1779
"registry should contain auto-registered `Bar` from `[Foo; 3]`"
1780
);
1781
1782
// === Vec === //
1783
let mut registry = TypeRegistry::empty();
1784
registry.register::<Vec<Foo>>();
1785
1786
assert!(
1787
registry.contains(TypeId::of::<Bar>()),
1788
"registry should contain auto-registered `Bar` from `Vec<Foo>`"
1789
);
1790
1791
// === HashMap === //
1792
let mut registry = TypeRegistry::empty();
1793
registry.register::<HashMap<i32, Foo>>();
1794
1795
assert!(
1796
registry.contains(TypeId::of::<Bar>()),
1797
"registry should contain auto-registered `Bar` from `HashMap<i32, Foo>`"
1798
);
1799
}
1800
1801
#[test]
1802
fn should_allow_dynamic_fields() {
1803
#[derive(Reflect)]
1804
#[reflect(from_reflect = false)]
1805
struct MyStruct(
1806
DynamicEnum,
1807
DynamicTupleStruct,
1808
DynamicStruct,
1809
DynamicMap,
1810
DynamicList,
1811
DynamicArray,
1812
DynamicTuple,
1813
i32,
1814
);
1815
1816
assert_impl_all!(MyStruct: Reflect, GetTypeRegistration);
1817
1818
let mut registry = TypeRegistry::empty();
1819
registry.register::<MyStruct>();
1820
1821
assert_eq!(2, registry.iter().count());
1822
assert!(registry.contains(TypeId::of::<MyStruct>()));
1823
assert!(registry.contains(TypeId::of::<i32>()));
1824
}
1825
1826
#[test]
1827
fn should_not_auto_register_existing_types() {
1828
#[derive(Reflect)]
1829
struct Foo {
1830
bar: Bar,
1831
}
1832
1833
#[derive(Reflect, Default)]
1834
struct Bar(usize);
1835
1836
let mut registry = TypeRegistry::empty();
1837
registry.register::<Bar>();
1838
registry.register_type_data::<Bar, ReflectDefault>();
1839
registry.register::<Foo>();
1840
1841
assert!(
1842
registry
1843
.get_type_data::<ReflectDefault>(TypeId::of::<Bar>())
1844
.is_some(),
1845
"registry should contain existing registration for `Bar`"
1846
);
1847
}
1848
1849
#[test]
1850
fn reflect_serialize() {
1851
#[derive(Reflect)]
1852
struct Foo {
1853
a: u32,
1854
#[reflect(ignore)]
1855
_b: u32,
1856
c: Vec<isize>,
1857
d: HashMap<usize, i8>,
1858
e: Bar,
1859
f: String,
1860
g: (i32, Vec<isize>, Bar),
1861
h: [u32; 2],
1862
}
1863
1864
#[derive(Reflect, Serialize, Deserialize)]
1865
#[reflect(Serialize, Deserialize)]
1866
struct Bar {
1867
x: u32,
1868
}
1869
1870
let mut hash_map = <HashMap<_, _>>::default();
1871
hash_map.insert(1, 1);
1872
hash_map.insert(2, 2);
1873
let foo = Foo {
1874
a: 1,
1875
_b: 1,
1876
c: vec![1, 2],
1877
d: hash_map,
1878
e: Bar { x: 1 },
1879
f: "hi".to_string(),
1880
g: (1, vec![1, 2], Bar { x: 1 }),
1881
h: [2; 2],
1882
};
1883
1884
let mut registry = TypeRegistry::default();
1885
registry.register::<u32>();
1886
registry.register::<i8>();
1887
registry.register::<i32>();
1888
registry.register::<usize>();
1889
registry.register::<isize>();
1890
registry.register::<Foo>();
1891
registry.register::<Bar>();
1892
registry.register::<String>();
1893
registry.register::<Vec<isize>>();
1894
registry.register::<HashMap<usize, i8>>();
1895
registry.register::<(i32, Vec<isize>, Bar)>();
1896
registry.register::<[u32; 2]>();
1897
1898
let serializer = ReflectSerializer::new(&foo, &registry);
1899
let serialized = to_string_pretty(&serializer, PrettyConfig::default()).unwrap();
1900
1901
let mut deserializer = Deserializer::from_str(&serialized).unwrap();
1902
let reflect_deserializer = ReflectDeserializer::new(&registry);
1903
let value = reflect_deserializer.deserialize(&mut deserializer).unwrap();
1904
let roundtrip_foo = Foo::from_reflect(value.as_partial_reflect()).unwrap();
1905
1906
assert!(foo.reflect_partial_eq(&roundtrip_foo).unwrap());
1907
}
1908
1909
#[test]
1910
fn reflect_downcast() {
1911
#[derive(Reflect, Clone, Debug, PartialEq)]
1912
struct Bar {
1913
y: u8,
1914
}
1915
1916
#[derive(Reflect, Clone, Debug, PartialEq)]
1917
struct Foo {
1918
x: i32,
1919
s: String,
1920
b: Bar,
1921
u: usize,
1922
t: ([f32; 3], String),
1923
v: Cow<'static, str>,
1924
w: Cow<'static, [u8]>,
1925
}
1926
1927
let foo = Foo {
1928
x: 123,
1929
s: "String".to_string(),
1930
b: Bar { y: 255 },
1931
u: 1111111111111,
1932
t: ([3.0, 2.0, 1.0], "Tuple String".to_string()),
1933
v: Cow::Owned("Cow String".to_string()),
1934
w: Cow::Owned(vec![1, 2, 3]),
1935
};
1936
1937
let foo2: Box<dyn Reflect> = Box::new(foo.clone());
1938
1939
assert_eq!(foo, *foo2.downcast::<Foo>().unwrap());
1940
}
1941
1942
#[test]
1943
fn should_drain_fields() {
1944
let array_value: Box<dyn Array> = Box::new([123_i32, 321_i32]);
1945
let fields = array_value.drain();
1946
assert!(fields[0].reflect_partial_eq(&123_i32).unwrap_or_default());
1947
assert!(fields[1].reflect_partial_eq(&321_i32).unwrap_or_default());
1948
1949
let mut list_value: Box<dyn List> = Box::new(vec![123_i32, 321_i32]);
1950
let fields = list_value.drain();
1951
assert!(fields[0].reflect_partial_eq(&123_i32).unwrap_or_default());
1952
assert!(fields[1].reflect_partial_eq(&321_i32).unwrap_or_default());
1953
1954
let tuple_value: Box<dyn Tuple> = Box::new((123_i32, 321_i32));
1955
let fields = tuple_value.drain();
1956
assert!(fields[0].reflect_partial_eq(&123_i32).unwrap_or_default());
1957
assert!(fields[1].reflect_partial_eq(&321_i32).unwrap_or_default());
1958
1959
let mut map_value: Box<dyn Map> =
1960
Box::new([(123_i32, 321_i32)].into_iter().collect::<HashMap<_, _>>());
1961
let fields = map_value.drain();
1962
assert!(fields[0].0.reflect_partial_eq(&123_i32).unwrap_or_default());
1963
assert!(fields[0].1.reflect_partial_eq(&321_i32).unwrap_or_default());
1964
}
1965
1966
#[test]
1967
fn reflect_take() {
1968
#[derive(Reflect, Debug, PartialEq)]
1969
#[reflect(PartialEq)]
1970
struct Bar {
1971
x: u32,
1972
}
1973
1974
let x: Box<dyn Reflect> = Box::new(Bar { x: 2 });
1975
let y = x.take::<Bar>().unwrap();
1976
assert_eq!(y, Bar { x: 2 });
1977
}
1978
1979
#[test]
1980
fn not_dynamic_names() {
1981
let list = Vec::<usize>::new();
1982
let dyn_list = list.to_dynamic_list();
1983
assert_ne!(dyn_list.reflect_type_path(), Vec::<usize>::type_path());
1984
1985
let array = [b'0'; 4];
1986
let dyn_array = array.to_dynamic_array();
1987
assert_ne!(dyn_array.reflect_type_path(), <[u8; 4]>::type_path());
1988
1989
let map = HashMap::<usize, String>::default();
1990
let dyn_map = map.to_dynamic_map();
1991
assert_ne!(
1992
dyn_map.reflect_type_path(),
1993
HashMap::<usize, String>::type_path()
1994
);
1995
1996
let tuple = (0usize, "1".to_string(), 2.0f32);
1997
let mut dyn_tuple = tuple.to_dynamic_tuple();
1998
dyn_tuple.insert::<usize>(3);
1999
assert_ne!(
2000
dyn_tuple.reflect_type_path(),
2001
<(usize, String, f32, usize)>::type_path()
2002
);
2003
2004
#[derive(Reflect)]
2005
struct TestStruct {
2006
a: usize,
2007
}
2008
let struct_ = TestStruct { a: 0 };
2009
let dyn_struct = struct_.to_dynamic_struct();
2010
assert_ne!(dyn_struct.reflect_type_path(), TestStruct::type_path());
2011
2012
#[derive(Reflect)]
2013
struct TestTupleStruct(usize);
2014
let tuple_struct = TestTupleStruct(0);
2015
let dyn_tuple_struct = tuple_struct.to_dynamic_tuple_struct();
2016
assert_ne!(
2017
dyn_tuple_struct.reflect_type_path(),
2018
TestTupleStruct::type_path()
2019
);
2020
}
2021
2022
macro_rules! assert_type_paths {
2023
($($ty:ty => $long:literal, $short:literal,)*) => {
2024
$(
2025
assert_eq!(<$ty as TypePath>::type_path(), $long);
2026
assert_eq!(<$ty as TypePath>::short_type_path(), $short);
2027
)*
2028
};
2029
}
2030
2031
#[test]
2032
fn reflect_type_path() {
2033
#[derive(TypePath)]
2034
struct Param;
2035
2036
#[derive(TypePath)]
2037
struct Derive;
2038
2039
#[derive(TypePath)]
2040
#[type_path = "my_alias"]
2041
struct DerivePath;
2042
2043
#[derive(TypePath)]
2044
#[type_path = "my_alias"]
2045
#[type_name = "MyDerivePathName"]
2046
struct DerivePathName;
2047
2048
#[derive(TypePath)]
2049
struct DeriveG<T>(PhantomData<T>);
2050
2051
#[derive(TypePath)]
2052
#[type_path = "my_alias"]
2053
struct DerivePathG<T, const N: usize>(PhantomData<T>);
2054
2055
#[derive(TypePath)]
2056
#[type_path = "my_alias"]
2057
#[type_name = "MyDerivePathNameG"]
2058
struct DerivePathNameG<T>(PhantomData<T>);
2059
2060
struct Macro;
2061
impl_type_path!((in my_alias) Macro);
2062
2063
struct MacroName;
2064
impl_type_path!((in my_alias as MyMacroName) MacroName);
2065
2066
struct MacroG<T, const N: usize>(PhantomData<T>);
2067
impl_type_path!((in my_alias) MacroG<T, const N: usize>);
2068
2069
struct MacroNameG<T>(PhantomData<T>);
2070
impl_type_path!((in my_alias as MyMacroNameG) MacroNameG<T>);
2071
2072
assert_type_paths! {
2073
Derive => "bevy_reflect::tests::Derive", "Derive",
2074
DerivePath => "my_alias::DerivePath", "DerivePath",
2075
DerivePathName => "my_alias::MyDerivePathName", "MyDerivePathName",
2076
DeriveG<Param> => "bevy_reflect::tests::DeriveG<bevy_reflect::tests::Param>", "DeriveG<Param>",
2077
DerivePathG<Param, 10> => "my_alias::DerivePathG<bevy_reflect::tests::Param, 10>", "DerivePathG<Param, 10>",
2078
DerivePathNameG<Param> => "my_alias::MyDerivePathNameG<bevy_reflect::tests::Param>", "MyDerivePathNameG<Param>",
2079
Macro => "my_alias::Macro", "Macro",
2080
MacroName => "my_alias::MyMacroName", "MyMacroName",
2081
MacroG<Param, 10> => "my_alias::MacroG<bevy_reflect::tests::Param, 10>", "MacroG<Param, 10>",
2082
MacroNameG<Param> => "my_alias::MyMacroNameG<bevy_reflect::tests::Param>", "MyMacroNameG<Param>",
2083
}
2084
}
2085
2086
#[test]
2087
fn std_type_paths() {
2088
#[derive(Clone)]
2089
struct Type;
2090
2091
impl TypePath for Type {
2092
fn type_path() -> &'static str {
2093
// for brevity in tests
2094
"Long"
2095
}
2096
2097
fn short_type_path() -> &'static str {
2098
"Short"
2099
}
2100
}
2101
2102
assert_type_paths! {
2103
u8 => "u8", "u8",
2104
Type => "Long", "Short",
2105
&Type => "&Long", "&Short",
2106
[Type] => "[Long]", "[Short]",
2107
&[Type] => "&[Long]", "&[Short]",
2108
[Type; 0] => "[Long; 0]", "[Short; 0]",
2109
[Type; 100] => "[Long; 100]", "[Short; 100]",
2110
() => "()", "()",
2111
(Type,) => "(Long,)", "(Short,)",
2112
(Type, Type) => "(Long, Long)", "(Short, Short)",
2113
(Type, Type, Type) => "(Long, Long, Long)", "(Short, Short, Short)",
2114
Cow<'static, Type> => "alloc::borrow::Cow<Long>", "Cow<Short>",
2115
}
2116
}
2117
2118
#[test]
2119
fn reflect_type_info() {
2120
// TypeInfo
2121
let info = i32::type_info();
2122
assert_eq!(i32::type_path(), info.type_path());
2123
assert_eq!(TypeId::of::<i32>(), info.type_id());
2124
2125
// TypeInfo (unsized)
2126
assert_eq!(
2127
TypeId::of::<dyn Reflect>(),
2128
<dyn Reflect as Typed>::type_info().type_id()
2129
);
2130
2131
// TypeInfo (instance)
2132
let value: &dyn Reflect = &123_i32;
2133
let info = value.reflect_type_info();
2134
assert!(info.is::<i32>());
2135
2136
// Struct
2137
#[derive(Reflect)]
2138
struct MyStruct {
2139
foo: i32,
2140
bar: usize,
2141
}
2142
2143
let info = MyStruct::type_info().as_struct().unwrap();
2144
assert!(info.is::<MyStruct>());
2145
assert_eq!(MyStruct::type_path(), info.type_path());
2146
assert_eq!(i32::type_path(), info.field("foo").unwrap().type_path());
2147
assert_eq!(TypeId::of::<i32>(), info.field("foo").unwrap().type_id());
2148
assert!(info.field("foo").unwrap().type_info().unwrap().is::<i32>());
2149
assert!(info.field("foo").unwrap().is::<i32>());
2150
assert_eq!("foo", info.field("foo").unwrap().name());
2151
assert_eq!(usize::type_path(), info.field_at(1).unwrap().type_path());
2152
2153
let value: &dyn Reflect = &MyStruct { foo: 123, bar: 321 };
2154
let info = value.reflect_type_info();
2155
assert!(info.is::<MyStruct>());
2156
2157
// Struct (generic)
2158
#[derive(Reflect)]
2159
struct MyGenericStruct<T> {
2160
foo: T,
2161
bar: usize,
2162
}
2163
2164
let info = <MyGenericStruct<i32>>::type_info().as_struct().unwrap();
2165
assert!(info.is::<MyGenericStruct<i32>>());
2166
assert_eq!(MyGenericStruct::<i32>::type_path(), info.type_path());
2167
assert_eq!(i32::type_path(), info.field("foo").unwrap().type_path());
2168
assert_eq!("foo", info.field("foo").unwrap().name());
2169
assert!(info.field("foo").unwrap().type_info().unwrap().is::<i32>());
2170
assert_eq!(usize::type_path(), info.field_at(1).unwrap().type_path());
2171
2172
let value: &dyn Reflect = &MyGenericStruct {
2173
foo: String::from("Hello!"),
2174
bar: 321,
2175
};
2176
let info = value.reflect_type_info();
2177
assert!(info.is::<MyGenericStruct<String>>());
2178
2179
// Struct (dynamic field)
2180
#[derive(Reflect)]
2181
#[reflect(from_reflect = false)]
2182
struct MyDynamicStruct {
2183
foo: DynamicStruct,
2184
bar: usize,
2185
}
2186
2187
let info = MyDynamicStruct::type_info();
2188
if let TypeInfo::Struct(info) = info {
2189
assert!(info.is::<MyDynamicStruct>());
2190
assert_eq!(MyDynamicStruct::type_path(), info.type_path());
2191
assert_eq!(
2192
DynamicStruct::type_path(),
2193
info.field("foo").unwrap().type_path()
2194
);
2195
assert_eq!("foo", info.field("foo").unwrap().name());
2196
assert!(info.field("foo").unwrap().type_info().is_none());
2197
assert_eq!(usize::type_path(), info.field_at(1).unwrap().type_path());
2198
} else {
2199
panic!("Expected `TypeInfo::Struct`");
2200
}
2201
2202
let value: &dyn Reflect = &MyDynamicStruct {
2203
foo: DynamicStruct::default(),
2204
bar: 321,
2205
};
2206
let info = value.reflect_type_info();
2207
assert!(info.is::<MyDynamicStruct>());
2208
2209
// Tuple Struct
2210
#[derive(Reflect)]
2211
struct MyTupleStruct(usize, i32, MyStruct);
2212
2213
let info = MyTupleStruct::type_info().as_tuple_struct().unwrap();
2214
2215
assert!(info.is::<MyTupleStruct>());
2216
assert_eq!(MyTupleStruct::type_path(), info.type_path());
2217
assert_eq!(i32::type_path(), info.field_at(1).unwrap().type_path());
2218
assert!(info.field_at(1).unwrap().type_info().unwrap().is::<i32>());
2219
assert!(info.field_at(1).unwrap().is::<i32>());
2220
2221
// Tuple
2222
type MyTuple = (u32, f32, String);
2223
2224
let info = MyTuple::type_info().as_tuple().unwrap();
2225
2226
assert!(info.is::<MyTuple>());
2227
assert_eq!(MyTuple::type_path(), info.type_path());
2228
assert_eq!(f32::type_path(), info.field_at(1).unwrap().type_path());
2229
assert!(info.field_at(1).unwrap().type_info().unwrap().is::<f32>());
2230
2231
let value: &dyn Reflect = &(123_u32, 1.23_f32, String::from("Hello!"));
2232
let info = value.reflect_type_info();
2233
assert!(info.is::<MyTuple>());
2234
2235
// List
2236
type MyList = Vec<usize>;
2237
2238
let info = MyList::type_info().as_list().unwrap();
2239
2240
assert!(info.is::<MyList>());
2241
assert!(info.item_ty().is::<usize>());
2242
assert!(info.item_info().unwrap().is::<usize>());
2243
assert_eq!(MyList::type_path(), info.type_path());
2244
assert_eq!(usize::type_path(), info.item_ty().path());
2245
2246
let value: &dyn Reflect = &vec![123_usize];
2247
let info = value.reflect_type_info();
2248
assert!(info.is::<MyList>());
2249
2250
// List (SmallVec)
2251
#[cfg(feature = "smallvec")]
2252
{
2253
type MySmallVec = smallvec::SmallVec<[String; 2]>;
2254
2255
let info = MySmallVec::type_info().as_list().unwrap();
2256
assert!(info.is::<MySmallVec>());
2257
assert!(info.item_ty().is::<String>());
2258
assert!(info.item_info().unwrap().is::<String>());
2259
assert_eq!(MySmallVec::type_path(), info.type_path());
2260
assert_eq!(String::type_path(), info.item_ty().path());
2261
2262
let value: MySmallVec = smallvec::smallvec![String::default(); 2];
2263
let value: &dyn Reflect = &value;
2264
let info = value.reflect_type_info();
2265
assert!(info.is::<MySmallVec>());
2266
}
2267
2268
// Array
2269
type MyArray = [usize; 3];
2270
2271
let info = MyArray::type_info().as_array().unwrap();
2272
assert!(info.is::<MyArray>());
2273
assert!(info.item_ty().is::<usize>());
2274
assert!(info.item_info().unwrap().is::<usize>());
2275
assert_eq!(MyArray::type_path(), info.type_path());
2276
assert_eq!(usize::type_path(), info.item_ty().path());
2277
assert_eq!(3, info.capacity());
2278
2279
let value: &dyn Reflect = &[1usize, 2usize, 3usize];
2280
let info = value.reflect_type_info();
2281
assert!(info.is::<MyArray>());
2282
2283
// Cow<'static, str>
2284
type MyCowStr = Cow<'static, str>;
2285
2286
let info = MyCowStr::type_info().as_opaque().unwrap();
2287
2288
assert!(info.is::<MyCowStr>());
2289
assert_eq!(core::any::type_name::<MyCowStr>(), info.type_path());
2290
2291
let value: &dyn Reflect = &Cow::<'static, str>::Owned("Hello!".to_string());
2292
let info = value.reflect_type_info();
2293
assert!(info.is::<MyCowStr>());
2294
2295
// Cow<'static, [u8]>
2296
type MyCowSlice = Cow<'static, [u8]>;
2297
2298
let info = MyCowSlice::type_info().as_list().unwrap();
2299
2300
assert!(info.is::<MyCowSlice>());
2301
assert!(info.item_ty().is::<u8>());
2302
assert!(info.item_info().unwrap().is::<u8>());
2303
assert_eq!(core::any::type_name::<MyCowSlice>(), info.type_path());
2304
assert_eq!(core::any::type_name::<u8>(), info.item_ty().path());
2305
2306
let value: &dyn Reflect = &Cow::<'static, [u8]>::Owned(vec![0, 1, 2, 3]);
2307
let info = value.reflect_type_info();
2308
assert!(info.is::<MyCowSlice>());
2309
2310
// Map
2311
type MyMap = HashMap<usize, f32>;
2312
2313
let info = MyMap::type_info().as_map().unwrap();
2314
2315
assert!(info.is::<MyMap>());
2316
assert!(info.key_ty().is::<usize>());
2317
assert!(info.value_ty().is::<f32>());
2318
assert!(info.key_info().unwrap().is::<usize>());
2319
assert!(info.value_info().unwrap().is::<f32>());
2320
assert_eq!(MyMap::type_path(), info.type_path());
2321
assert_eq!(usize::type_path(), info.key_ty().path());
2322
assert_eq!(f32::type_path(), info.value_ty().path());
2323
2324
let value: &dyn Reflect = &MyMap::default();
2325
let info = value.reflect_type_info();
2326
assert!(info.is::<MyMap>());
2327
2328
// Value
2329
type MyValue = String;
2330
2331
let info = MyValue::type_info().as_opaque().unwrap();
2332
2333
assert!(info.is::<MyValue>());
2334
assert_eq!(MyValue::type_path(), info.type_path());
2335
2336
let value: &dyn Reflect = &String::from("Hello!");
2337
let info = value.reflect_type_info();
2338
assert!(info.is::<MyValue>());
2339
}
2340
2341
#[test]
2342
fn get_represented_kind_info() {
2343
#[derive(Reflect)]
2344
struct SomeStruct;
2345
2346
#[derive(Reflect)]
2347
struct SomeTupleStruct(f32);
2348
2349
#[derive(Reflect)]
2350
enum SomeEnum {
2351
Foo,
2352
Bar,
2353
}
2354
2355
let dyn_struct: &dyn Struct = &SomeStruct;
2356
let _: &StructInfo = dyn_struct.get_represented_struct_info().unwrap();
2357
2358
let dyn_map: &dyn Map = &HashMap::<(), ()>::default();
2359
let _: &MapInfo = dyn_map.get_represented_map_info().unwrap();
2360
2361
let dyn_array: &dyn Array = &[1, 2, 3];
2362
let _: &ArrayInfo = dyn_array.get_represented_array_info().unwrap();
2363
2364
let dyn_list: &dyn List = &vec![1, 2, 3];
2365
let _: &ListInfo = dyn_list.get_represented_list_info().unwrap();
2366
2367
let dyn_tuple_struct: &dyn TupleStruct = &SomeTupleStruct(5.0);
2368
let _: &TupleStructInfo = dyn_tuple_struct
2369
.get_represented_tuple_struct_info()
2370
.unwrap();
2371
2372
let dyn_enum: &dyn Enum = &SomeEnum::Foo;
2373
let _: &EnumInfo = dyn_enum.get_represented_enum_info().unwrap();
2374
}
2375
2376
#[test]
2377
fn should_permit_higher_ranked_lifetimes() {
2378
#[derive(Reflect)]
2379
#[reflect(from_reflect = false)]
2380
struct TestStruct {
2381
#[reflect(ignore)]
2382
_hrl: for<'a> fn(&'a str) -> &'a str,
2383
}
2384
2385
impl Default for TestStruct {
2386
fn default() -> Self {
2387
TestStruct {
2388
_hrl: |input| input,
2389
}
2390
}
2391
}
2392
2393
fn get_type_registration<T: GetTypeRegistration>() {}
2394
get_type_registration::<TestStruct>();
2395
}
2396
2397
#[test]
2398
fn should_permit_valid_represented_type_for_dynamic() {
2399
let type_info = <[i32; 2] as Typed>::type_info();
2400
let mut dynamic_array = [123; 2].to_dynamic_array();
2401
dynamic_array.set_represented_type(Some(type_info));
2402
}
2403
2404
#[test]
2405
#[should_panic(expected = "expected TypeInfo::Array but received")]
2406
fn should_prohibit_invalid_represented_type_for_dynamic() {
2407
let type_info = <(i32, i32) as Typed>::type_info();
2408
let mut dynamic_array = [123; 2].to_dynamic_array();
2409
dynamic_array.set_represented_type(Some(type_info));
2410
}
2411
2412
#[cfg(feature = "documentation")]
2413
mod docstrings {
2414
use super::*;
2415
2416
#[test]
2417
fn should_not_contain_docs() {
2418
// Regular comments do not count as doc comments,
2419
// and are therefore not reflected.
2420
#[derive(Reflect)]
2421
struct SomeStruct;
2422
2423
let info = <SomeStruct as Typed>::type_info();
2424
assert_eq!(None, info.docs());
2425
2426
// Block comments do not count as doc comments,
2427
// and are therefore not reflected.
2428
#[derive(Reflect)]
2429
struct SomeOtherStruct;
2430
2431
let info = <SomeOtherStruct as Typed>::type_info();
2432
assert_eq!(None, info.docs());
2433
}
2434
2435
#[test]
2436
fn should_contain_docs() {
2437
/// Some struct.
2438
///
2439
/// # Example
2440
///
2441
/// ```ignore (This is only used for a unit test, no need to doc test)
2442
/// let some_struct = SomeStruct;
2443
/// ```
2444
#[derive(Reflect)]
2445
struct SomeStruct;
2446
2447
let info = <SomeStruct as Typed>::type_info();
2448
assert_eq!(
2449
Some(" Some struct.\n\n # Example\n\n ```ignore (This is only used for a unit test, no need to doc test)\n let some_struct = SomeStruct;\n ```"),
2450
info.docs()
2451
);
2452
2453
#[doc = "The compiler automatically converts `///`-style comments into `#[doc]` attributes."]
2454
#[doc = "Of course, you _could_ use the attribute directly if you wanted to."]
2455
#[doc = "Both will be reflected."]
2456
#[derive(Reflect)]
2457
struct SomeOtherStruct;
2458
2459
let info = <SomeOtherStruct as Typed>::type_info();
2460
assert_eq!(
2461
Some("The compiler automatically converts `///`-style comments into `#[doc]` attributes.\nOf course, you _could_ use the attribute directly if you wanted to.\nBoth will be reflected."),
2462
info.docs()
2463
);
2464
2465
/// Some tuple struct.
2466
#[derive(Reflect)]
2467
struct SomeTupleStruct(usize);
2468
2469
let info = <SomeTupleStruct as Typed>::type_info();
2470
assert_eq!(Some(" Some tuple struct."), info.docs());
2471
2472
/// Some enum.
2473
#[derive(Reflect)]
2474
enum SomeEnum {
2475
Foo,
2476
}
2477
2478
let info = <SomeEnum as Typed>::type_info();
2479
assert_eq!(Some(" Some enum."), info.docs());
2480
2481
#[derive(Clone)]
2482
struct SomePrimitive;
2483
impl_reflect_opaque!(
2484
/// Some primitive for which we have attributed custom documentation.
2485
(in bevy_reflect::tests) SomePrimitive
2486
);
2487
2488
let info = <SomePrimitive as Typed>::type_info();
2489
assert_eq!(
2490
Some(" Some primitive for which we have attributed custom documentation."),
2491
info.docs()
2492
);
2493
}
2494
2495
#[test]
2496
fn fields_should_contain_docs() {
2497
#[derive(Reflect)]
2498
struct SomeStruct {
2499
/// The name
2500
name: String,
2501
/// The index
2502
index: usize,
2503
// Not documented...
2504
data: Vec<i32>,
2505
}
2506
2507
let info = <SomeStruct as Typed>::type_info().as_struct().unwrap();
2508
2509
let mut fields = info.iter();
2510
assert_eq!(Some(" The name"), fields.next().unwrap().docs());
2511
assert_eq!(Some(" The index"), fields.next().unwrap().docs());
2512
assert_eq!(None, fields.next().unwrap().docs());
2513
}
2514
2515
#[test]
2516
fn variants_should_contain_docs() {
2517
#[derive(Reflect)]
2518
enum SomeEnum {
2519
// Not documented...
2520
Nothing,
2521
/// Option A
2522
A(
2523
/// Index
2524
usize,
2525
),
2526
/// Option B
2527
B {
2528
/// Name
2529
name: String,
2530
},
2531
}
2532
2533
let info = <SomeEnum as Typed>::type_info().as_enum().unwrap();
2534
2535
let mut variants = info.iter();
2536
assert_eq!(None, variants.next().unwrap().docs());
2537
2538
let variant = variants.next().unwrap().as_tuple_variant().unwrap();
2539
assert_eq!(Some(" Option A"), variant.docs());
2540
let field = variant.field_at(0).unwrap();
2541
assert_eq!(Some(" Index"), field.docs());
2542
2543
let variant = variants.next().unwrap().as_struct_variant().unwrap();
2544
assert_eq!(Some(" Option B"), variant.docs());
2545
let field = variant.field_at(0).unwrap();
2546
assert_eq!(Some(" Name"), field.docs());
2547
}
2548
}
2549
2550
#[test]
2551
fn into_reflect() {
2552
trait TestTrait: Reflect {}
2553
2554
#[derive(Reflect)]
2555
struct TestStruct;
2556
2557
impl TestTrait for TestStruct {}
2558
2559
let trait_object: Box<dyn TestTrait> = Box::new(TestStruct);
2560
2561
// Should compile:
2562
let _ = trait_object.into_reflect();
2563
}
2564
2565
#[test]
2566
fn as_reflect() {
2567
trait TestTrait: Reflect {}
2568
2569
#[derive(Reflect)]
2570
struct TestStruct;
2571
2572
impl TestTrait for TestStruct {}
2573
2574
let trait_object: Box<dyn TestTrait> = Box::new(TestStruct);
2575
2576
// Should compile:
2577
let _ = trait_object.as_reflect();
2578
}
2579
2580
#[test]
2581
fn should_reflect_debug() {
2582
#[derive(Reflect)]
2583
struct Test {
2584
value: usize,
2585
list: Vec<String>,
2586
array: [f32; 3],
2587
map: HashMap<i32, f32>,
2588
a_struct: SomeStruct,
2589
a_tuple_struct: SomeTupleStruct,
2590
enum_unit: SomeEnum,
2591
enum_tuple: SomeEnum,
2592
enum_struct: SomeEnum,
2593
custom: CustomDebug,
2594
#[reflect(ignore)]
2595
#[expect(dead_code, reason = "This value is intended to not be reflected.")]
2596
ignored: isize,
2597
}
2598
2599
#[derive(Reflect)]
2600
struct SomeStruct {
2601
foo: String,
2602
}
2603
2604
#[derive(Reflect)]
2605
enum SomeEnum {
2606
A,
2607
B(usize),
2608
C { value: i32 },
2609
}
2610
2611
#[derive(Reflect)]
2612
struct SomeTupleStruct(String);
2613
2614
#[derive(Reflect)]
2615
#[reflect(Debug)]
2616
struct CustomDebug;
2617
impl Debug for CustomDebug {
2618
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
2619
f.write_str("Cool debug!")
2620
}
2621
}
2622
2623
let mut map = <HashMap<_, _>>::default();
2624
map.insert(123, 1.23);
2625
2626
let test = Test {
2627
value: 123,
2628
list: vec![String::from("A"), String::from("B"), String::from("C")],
2629
array: [1.0, 2.0, 3.0],
2630
map,
2631
a_struct: SomeStruct {
2632
foo: String::from("A Struct!"),
2633
},
2634
a_tuple_struct: SomeTupleStruct(String::from("A Tuple Struct!")),
2635
enum_unit: SomeEnum::A,
2636
enum_tuple: SomeEnum::B(123),
2637
enum_struct: SomeEnum::C { value: 321 },
2638
custom: CustomDebug,
2639
ignored: 321,
2640
};
2641
2642
let reflected: &dyn Reflect = &test;
2643
let expected = r#"
2644
bevy_reflect::tests::Test {
2645
value: 123,
2646
list: [
2647
"A",
2648
"B",
2649
"C",
2650
],
2651
array: [
2652
1.0,
2653
2.0,
2654
3.0,
2655
],
2656
map: {
2657
123: 1.23,
2658
},
2659
a_struct: bevy_reflect::tests::SomeStruct {
2660
foo: "A Struct!",
2661
},
2662
a_tuple_struct: bevy_reflect::tests::SomeTupleStruct(
2663
"A Tuple Struct!",
2664
),
2665
enum_unit: A,
2666
enum_tuple: B(
2667
123,
2668
),
2669
enum_struct: C {
2670
value: 321,
2671
},
2672
custom: Cool debug!,
2673
}"#;
2674
2675
assert_eq!(expected, format!("\n{reflected:#?}"));
2676
}
2677
2678
#[test]
2679
fn multiple_reflect_lists() {
2680
#[derive(Hash, PartialEq, Reflect)]
2681
#[reflect(Debug, Hash)]
2682
#[reflect(PartialEq)]
2683
struct Foo(i32);
2684
2685
impl Debug for Foo {
2686
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
2687
write!(f, "Foo")
2688
}
2689
}
2690
2691
let foo = Foo(123);
2692
let foo: &dyn PartialReflect = &foo;
2693
2694
assert!(foo.reflect_hash().is_some());
2695
assert_eq!(Some(true), foo.reflect_partial_eq(foo));
2696
assert_eq!("Foo".to_string(), format!("{foo:?}"));
2697
}
2698
2699
#[test]
2700
fn custom_debug_function() {
2701
#[derive(Reflect)]
2702
#[reflect(Debug(custom_debug))]
2703
struct Foo {
2704
a: u32,
2705
}
2706
2707
fn custom_debug(_x: &Foo, f: &mut Formatter<'_>) -> core::fmt::Result {
2708
write!(f, "123")
2709
}
2710
2711
let foo = Foo { a: 1 };
2712
let foo: &dyn Reflect = &foo;
2713
2714
assert_eq!("123", format!("{foo:?}"));
2715
}
2716
2717
#[test]
2718
fn should_allow_custom_where() {
2719
#[derive(Reflect)]
2720
#[reflect(where T: Default)]
2721
struct Foo<T>(String, #[reflect(ignore)] PhantomData<T>);
2722
2723
#[derive(Default, TypePath)]
2724
struct Bar;
2725
2726
#[derive(TypePath)]
2727
struct Baz;
2728
2729
assert_impl_all!(Foo<Bar>: Reflect);
2730
assert_not_impl_all!(Foo<Baz>: Reflect);
2731
}
2732
2733
#[test]
2734
fn should_allow_empty_custom_where() {
2735
#[derive(Reflect)]
2736
#[reflect(where)]
2737
struct Foo<T>(String, #[reflect(ignore)] PhantomData<T>);
2738
2739
#[derive(TypePath)]
2740
struct Bar;
2741
2742
assert_impl_all!(Foo<Bar>: Reflect);
2743
}
2744
2745
#[test]
2746
fn should_allow_multiple_custom_where() {
2747
#[derive(Reflect)]
2748
#[reflect(where T: Default)]
2749
#[reflect(where U: core::ops::Add<T>)]
2750
struct Foo<T, U>(T, U);
2751
2752
#[derive(Reflect)]
2753
struct Baz {
2754
a: Foo<i32, i32>,
2755
b: Foo<u32, u32>,
2756
}
2757
2758
assert_impl_all!(Foo<i32, i32>: Reflect);
2759
assert_not_impl_all!(Foo<i32, usize>: Reflect);
2760
}
2761
2762
#[test]
2763
fn should_allow_custom_where_with_assoc_type() {
2764
trait Trait {
2765
type Assoc;
2766
}
2767
2768
// We don't need `T` to be `Reflect` since we only care about `T::Assoc`
2769
#[derive(Reflect)]
2770
#[reflect(where T::Assoc: core::fmt::Display)]
2771
struct Foo<T: Trait>(T::Assoc);
2772
2773
#[derive(TypePath)]
2774
struct Bar;
2775
2776
impl Trait for Bar {
2777
type Assoc = usize;
2778
}
2779
2780
#[derive(TypePath)]
2781
struct Baz;
2782
2783
impl Trait for Baz {
2784
type Assoc = (f32, f32);
2785
}
2786
2787
assert_impl_all!(Foo<Bar>: Reflect);
2788
assert_not_impl_all!(Foo<Baz>: Reflect);
2789
}
2790
2791
#[test]
2792
fn should_allow_empty_enums() {
2793
#[derive(Reflect)]
2794
enum Empty {}
2795
2796
assert_impl_all!(Empty: Reflect);
2797
}
2798
2799
#[test]
2800
fn recursive_typed_storage_does_not_hang() {
2801
#[derive(Reflect)]
2802
struct Recurse<T>(T);
2803
2804
let _ = <Recurse<Recurse<()>> as Typed>::type_info();
2805
let _ = <Recurse<Recurse<()>> as TypePath>::type_path();
2806
2807
#[derive(Reflect)]
2808
#[reflect(no_field_bounds)]
2809
struct SelfRecurse {
2810
recurse: Vec<SelfRecurse>,
2811
}
2812
2813
let _ = <SelfRecurse as Typed>::type_info();
2814
let _ = <SelfRecurse as TypePath>::type_path();
2815
2816
#[derive(Reflect)]
2817
#[reflect(no_field_bounds)]
2818
enum RecurseA {
2819
Recurse(RecurseB),
2820
}
2821
2822
#[derive(Reflect)]
2823
// `#[reflect(no_field_bounds)]` not needed since already added to `RecurseA`
2824
struct RecurseB {
2825
vector: Vec<RecurseA>,
2826
}
2827
2828
let _ = <RecurseA as Typed>::type_info();
2829
let _ = <RecurseA as TypePath>::type_path();
2830
let _ = <RecurseB as Typed>::type_info();
2831
let _ = <RecurseB as TypePath>::type_path();
2832
}
2833
2834
#[test]
2835
fn recursive_registration_does_not_hang() {
2836
#[derive(Reflect)]
2837
struct Recurse<T>(T);
2838
2839
let mut registry = TypeRegistry::empty();
2840
2841
registry.register::<Recurse<Recurse<()>>>();
2842
2843
#[derive(Reflect)]
2844
#[reflect(no_field_bounds)]
2845
struct SelfRecurse {
2846
recurse: Vec<SelfRecurse>,
2847
}
2848
2849
registry.register::<SelfRecurse>();
2850
2851
#[derive(Reflect)]
2852
#[reflect(no_field_bounds)]
2853
enum RecurseA {
2854
Recurse(RecurseB),
2855
}
2856
2857
#[derive(Reflect)]
2858
struct RecurseB {
2859
vector: Vec<RecurseA>,
2860
}
2861
2862
registry.register::<RecurseA>();
2863
assert!(registry.contains(TypeId::of::<RecurseA>()));
2864
assert!(registry.contains(TypeId::of::<RecurseB>()));
2865
}
2866
2867
#[test]
2868
fn can_opt_out_type_path() {
2869
#[derive(Reflect)]
2870
#[reflect(type_path = false)]
2871
struct Foo<T> {
2872
#[reflect(ignore)]
2873
_marker: PhantomData<T>,
2874
}
2875
2876
struct NotTypePath;
2877
2878
impl<T: 'static> TypePath for Foo<T> {
2879
fn type_path() -> &'static str {
2880
core::any::type_name::<Self>()
2881
}
2882
2883
fn short_type_path() -> &'static str {
2884
static CELL: GenericTypePathCell = GenericTypePathCell::new();
2885
CELL.get_or_insert::<Self, _>(|| ShortName::of::<Self>().to_string())
2886
}
2887
2888
fn type_ident() -> Option<&'static str> {
2889
Some("Foo")
2890
}
2891
2892
fn crate_name() -> Option<&'static str> {
2893
Some("bevy_reflect")
2894
}
2895
2896
fn module_path() -> Option<&'static str> {
2897
Some("bevy_reflect::tests")
2898
}
2899
}
2900
2901
// Can use `TypePath`
2902
let path = <Foo<NotTypePath> as TypePath>::type_path();
2903
assert_eq!("bevy_reflect::tests::can_opt_out_type_path::Foo<bevy_reflect::tests::can_opt_out_type_path::NotTypePath>", path);
2904
2905
// Can register the type
2906
let mut registry = TypeRegistry::default();
2907
registry.register::<Foo<NotTypePath>>();
2908
2909
let registration = registry.get(TypeId::of::<Foo<NotTypePath>>()).unwrap();
2910
assert_eq!(
2911
"Foo<NotTypePath>",
2912
registration.type_info().type_path_table().short_path()
2913
);
2914
}
2915
2916
#[test]
2917
fn dynamic_types_debug_format() {
2918
#[derive(Debug, Reflect)]
2919
struct TestTupleStruct(u32);
2920
2921
#[derive(Debug, Reflect)]
2922
enum TestEnum {
2923
A(u32),
2924
B,
2925
}
2926
2927
#[derive(Debug, Reflect)]
2928
// test DynamicStruct
2929
struct TestStruct {
2930
// test DynamicTuple
2931
tuple: (u32, u32),
2932
// test DynamicTupleStruct
2933
tuple_struct: TestTupleStruct,
2934
// test DynamicList
2935
list: Vec<u32>,
2936
// test DynamicArray
2937
array: [u32; 3],
2938
// test DynamicEnum
2939
e: TestEnum,
2940
// test DynamicMap
2941
map: HashMap<u32, u32>,
2942
// test reflected value
2943
value: u32,
2944
}
2945
let mut map = <HashMap<_, _>>::default();
2946
map.insert(9, 10);
2947
let mut test_struct: DynamicStruct = TestStruct {
2948
tuple: (0, 1),
2949
list: vec![2, 3, 4],
2950
array: [5, 6, 7],
2951
tuple_struct: TestTupleStruct(8),
2952
e: TestEnum::A(11),
2953
map,
2954
value: 12,
2955
}
2956
.to_dynamic_struct();
2957
2958
// test unknown DynamicStruct
2959
let mut test_unknown_struct = DynamicStruct::default();
2960
test_unknown_struct.insert("a", 13);
2961
test_struct.insert("unknown_struct", test_unknown_struct);
2962
// test unknown DynamicTupleStruct
2963
let mut test_unknown_tuple_struct = DynamicTupleStruct::default();
2964
test_unknown_tuple_struct.insert(14);
2965
test_struct.insert("unknown_tuplestruct", test_unknown_tuple_struct);
2966
assert_eq!(
2967
format!("{test_struct:?}"),
2968
"DynamicStruct(bevy_reflect::tests::TestStruct { \
2969
tuple: DynamicTuple((0, 1)), \
2970
tuple_struct: DynamicTupleStruct(bevy_reflect::tests::TestTupleStruct(8)), \
2971
list: DynamicList([2, 3, 4]), \
2972
array: DynamicArray([5, 6, 7]), \
2973
e: DynamicEnum(A(11)), \
2974
map: DynamicMap({9: 10}), \
2975
value: 12, \
2976
unknown_struct: DynamicStruct(_ { a: 13 }), \
2977
unknown_tuplestruct: DynamicTupleStruct(_(14)) \
2978
})"
2979
);
2980
}
2981
2982
#[test]
2983
fn assert_impl_reflect_macro_on_all() {
2984
struct Struct {
2985
foo: (),
2986
}
2987
struct TupleStruct(());
2988
enum Enum {
2989
Foo { foo: () },
2990
Bar(()),
2991
}
2992
2993
impl_reflect!(
2994
#[type_path = "my_crate::foo"]
2995
struct Struct {
2996
foo: (),
2997
}
2998
);
2999
3000
impl_reflect!(
3001
#[type_path = "my_crate::foo"]
3002
struct TupleStruct(());
3003
);
3004
3005
impl_reflect!(
3006
#[type_path = "my_crate::foo"]
3007
enum Enum {
3008
Foo { foo: () },
3009
Bar(()),
3010
}
3011
);
3012
3013
assert_impl_all!(Struct: Reflect);
3014
assert_impl_all!(TupleStruct: Reflect);
3015
assert_impl_all!(Enum: Reflect);
3016
}
3017
3018
#[test]
3019
fn should_reflect_remote_type() {
3020
mod external_crate {
3021
use alloc::string::String;
3022
3023
#[derive(Debug, Default)]
3024
pub struct TheirType {
3025
pub value: String,
3026
}
3027
}
3028
3029
// === Remote Wrapper === //
3030
#[reflect_remote(external_crate::TheirType)]
3031
#[derive(Debug, Default)]
3032
#[reflect(Debug, Default)]
3033
struct MyType {
3034
pub value: String,
3035
}
3036
3037
let mut patch = DynamicStruct::default();
3038
patch.set_represented_type(Some(MyType::type_info()));
3039
patch.insert("value", "Goodbye".to_string());
3040
3041
let mut data = MyType(external_crate::TheirType {
3042
value: "Hello".to_string(),
3043
});
3044
3045
assert_eq!("Hello", data.0.value);
3046
data.apply(&patch);
3047
assert_eq!("Goodbye", data.0.value);
3048
3049
// === Struct Container === //
3050
#[derive(Reflect, Debug)]
3051
#[reflect(from_reflect = false)]
3052
struct ContainerStruct {
3053
#[reflect(remote = MyType)]
3054
their_type: external_crate::TheirType,
3055
}
3056
3057
let mut patch = DynamicStruct::default();
3058
patch.set_represented_type(Some(ContainerStruct::type_info()));
3059
patch.insert(
3060
"their_type",
3061
MyType(external_crate::TheirType {
3062
value: "Goodbye".to_string(),
3063
}),
3064
);
3065
3066
let mut data = ContainerStruct {
3067
their_type: external_crate::TheirType {
3068
value: "Hello".to_string(),
3069
},
3070
};
3071
3072
assert_eq!("Hello", data.their_type.value);
3073
data.apply(&patch);
3074
assert_eq!("Goodbye", data.their_type.value);
3075
3076
// === Tuple Struct Container === //
3077
#[derive(Reflect, Debug)]
3078
struct ContainerTupleStruct(#[reflect(remote = MyType)] external_crate::TheirType);
3079
3080
let mut patch = DynamicTupleStruct::default();
3081
patch.set_represented_type(Some(ContainerTupleStruct::type_info()));
3082
patch.insert(MyType(external_crate::TheirType {
3083
value: "Goodbye".to_string(),
3084
}));
3085
3086
let mut data = ContainerTupleStruct(external_crate::TheirType {
3087
value: "Hello".to_string(),
3088
});
3089
3090
assert_eq!("Hello", data.0.value);
3091
data.apply(&patch);
3092
assert_eq!("Goodbye", data.0.value);
3093
}
3094
3095
#[test]
3096
fn should_reflect_remote_value_type() {
3097
mod external_crate {
3098
use alloc::string::String;
3099
3100
#[derive(Clone, Debug, Default)]
3101
pub struct TheirType {
3102
pub value: String,
3103
}
3104
}
3105
3106
// === Remote Wrapper === //
3107
#[reflect_remote(external_crate::TheirType)]
3108
#[derive(Clone, Debug, Default)]
3109
#[reflect(opaque)]
3110
#[reflect(Debug, Default)]
3111
struct MyType {
3112
pub value: String,
3113
}
3114
3115
let mut data = MyType(external_crate::TheirType {
3116
value: "Hello".to_string(),
3117
});
3118
3119
let patch = MyType(external_crate::TheirType {
3120
value: "Goodbye".to_string(),
3121
});
3122
3123
assert_eq!("Hello", data.0.value);
3124
data.apply(&patch);
3125
assert_eq!("Goodbye", data.0.value);
3126
3127
// === Struct Container === //
3128
#[derive(Reflect, Debug)]
3129
#[reflect(from_reflect = false)]
3130
struct ContainerStruct {
3131
#[reflect(remote = MyType)]
3132
their_type: external_crate::TheirType,
3133
}
3134
3135
let mut patch = DynamicStruct::default();
3136
patch.set_represented_type(Some(ContainerStruct::type_info()));
3137
patch.insert(
3138
"their_type",
3139
MyType(external_crate::TheirType {
3140
value: "Goodbye".to_string(),
3141
}),
3142
);
3143
3144
let mut data = ContainerStruct {
3145
their_type: external_crate::TheirType {
3146
value: "Hello".to_string(),
3147
},
3148
};
3149
3150
assert_eq!("Hello", data.their_type.value);
3151
data.apply(&patch);
3152
assert_eq!("Goodbye", data.their_type.value);
3153
3154
// === Tuple Struct Container === //
3155
#[derive(Reflect, Debug)]
3156
struct ContainerTupleStruct(#[reflect(remote = MyType)] external_crate::TheirType);
3157
3158
let mut patch = DynamicTupleStruct::default();
3159
patch.set_represented_type(Some(ContainerTupleStruct::type_info()));
3160
patch.insert(MyType(external_crate::TheirType {
3161
value: "Goodbye".to_string(),
3162
}));
3163
3164
let mut data = ContainerTupleStruct(external_crate::TheirType {
3165
value: "Hello".to_string(),
3166
});
3167
3168
assert_eq!("Hello", data.0.value);
3169
data.apply(&patch);
3170
assert_eq!("Goodbye", data.0.value);
3171
}
3172
3173
#[test]
3174
fn should_reflect_remote_type_from_module() {
3175
mod wrapper {
3176
use super::*;
3177
3178
// We have to place this module internally to this one to get around the following error:
3179
// ```
3180
// error[E0433]: failed to resolve: use of undeclared crate or module `external_crate`
3181
// ```
3182
pub mod external_crate {
3183
use alloc::string::String;
3184
3185
pub struct TheirType {
3186
pub value: String,
3187
}
3188
}
3189
3190
#[reflect_remote(external_crate::TheirType)]
3191
pub struct MyType {
3192
pub value: String,
3193
}
3194
}
3195
3196
#[derive(Reflect)]
3197
struct ContainerStruct {
3198
#[reflect(remote = wrapper::MyType)]
3199
their_type: wrapper::external_crate::TheirType,
3200
}
3201
}
3202
3203
#[test]
3204
fn should_reflect_remote_enum() {
3205
mod external_crate {
3206
use alloc::string::String;
3207
3208
#[derive(Debug, PartialEq, Eq)]
3209
pub enum TheirType {
3210
Unit,
3211
Tuple(usize),
3212
Struct { value: String },
3213
}
3214
}
3215
3216
// === Remote Wrapper === //
3217
#[reflect_remote(external_crate::TheirType)]
3218
#[derive(Debug)]
3219
#[reflect(Debug)]
3220
enum MyType {
3221
Unit,
3222
Tuple(usize),
3223
Struct { value: String },
3224
}
3225
3226
let mut patch = DynamicEnum::from(MyType(external_crate::TheirType::Tuple(123)));
3227
3228
let mut data = MyType(external_crate::TheirType::Unit);
3229
3230
assert_eq!(external_crate::TheirType::Unit, data.0);
3231
data.apply(&patch);
3232
assert_eq!(external_crate::TheirType::Tuple(123), data.0);
3233
3234
patch = DynamicEnum::from(MyType(external_crate::TheirType::Struct {
3235
value: "Hello world!".to_string(),
3236
}));
3237
3238
data.apply(&patch);
3239
assert_eq!(
3240
external_crate::TheirType::Struct {
3241
value: "Hello world!".to_string()
3242
},
3243
data.0
3244
);
3245
3246
// === Enum Container === //
3247
#[derive(Reflect, Debug, PartialEq)]
3248
enum ContainerEnum {
3249
Foo,
3250
Bar {
3251
#[reflect(remote = MyType)]
3252
their_type: external_crate::TheirType,
3253
},
3254
}
3255
3256
let patch = DynamicEnum::from(ContainerEnum::Bar {
3257
their_type: external_crate::TheirType::Tuple(123),
3258
});
3259
3260
let mut data = ContainerEnum::Foo;
3261
3262
assert_eq!(ContainerEnum::Foo, data);
3263
data.apply(&patch);
3264
assert_eq!(
3265
ContainerEnum::Bar {
3266
their_type: external_crate::TheirType::Tuple(123)
3267
},
3268
data
3269
);
3270
}
3271
3272
#[test]
3273
fn should_reflect_nested_remote_type() {
3274
mod external_crate {
3275
pub struct TheirOuter<T> {
3276
pub a: TheirInner<T>,
3277
pub b: TheirInner<bool>,
3278
}
3279
3280
pub struct TheirInner<T>(pub T);
3281
}
3282
3283
#[reflect_remote(external_crate::TheirOuter<T>)]
3284
struct MyOuter<T: FromReflect + Reflectable> {
3285
#[reflect(remote = MyInner<T>)]
3286
pub a: external_crate::TheirInner<T>,
3287
#[reflect(remote = MyInner<bool>)]
3288
pub b: external_crate::TheirInner<bool>,
3289
}
3290
3291
#[reflect_remote(external_crate::TheirInner<T>)]
3292
struct MyInner<T: FromReflect>(pub T);
3293
3294
let mut patch = DynamicStruct::default();
3295
patch.set_represented_type(Some(MyOuter::<i32>::type_info()));
3296
patch.insert("a", MyInner(external_crate::TheirInner(321_i32)));
3297
patch.insert("b", MyInner(external_crate::TheirInner(true)));
3298
3299
let mut data = MyOuter(external_crate::TheirOuter {
3300
a: external_crate::TheirInner(123_i32),
3301
b: external_crate::TheirInner(false),
3302
});
3303
3304
assert_eq!(123, data.0.a.0);
3305
assert!(!data.0.b.0);
3306
data.apply(&patch);
3307
assert_eq!(321, data.0.a.0);
3308
assert!(data.0.b.0);
3309
}
3310
3311
#[test]
3312
fn should_reflect_nested_remote_enum() {
3313
mod external_crate {
3314
use core::fmt::Debug;
3315
3316
#[derive(Debug)]
3317
pub enum TheirOuter<T: Debug> {
3318
Unit,
3319
Tuple(TheirInner<T>),
3320
Struct { value: TheirInner<T> },
3321
}
3322
#[derive(Debug)]
3323
pub enum TheirInner<T: Debug> {
3324
Unit,
3325
Tuple(T),
3326
Struct { value: T },
3327
}
3328
}
3329
3330
#[reflect_remote(external_crate::TheirOuter<T>)]
3331
#[derive(Debug)]
3332
enum MyOuter<T: FromReflect + Reflectable + Debug> {
3333
Unit,
3334
Tuple(#[reflect(remote = MyInner<T>)] external_crate::TheirInner<T>),
3335
Struct {
3336
#[reflect(remote = MyInner<T>)]
3337
value: external_crate::TheirInner<T>,
3338
},
3339
}
3340
3341
#[reflect_remote(external_crate::TheirInner<T>)]
3342
#[derive(Debug)]
3343
enum MyInner<T: FromReflect + Debug> {
3344
Unit,
3345
Tuple(T),
3346
Struct { value: T },
3347
}
3348
3349
let mut patch = DynamicEnum::default();
3350
let mut value = DynamicStruct::default();
3351
value.insert("value", MyInner(external_crate::TheirInner::Tuple(123)));
3352
patch.set_variant("Struct", value);
3353
3354
let mut data = MyOuter(external_crate::TheirOuter::<i32>::Unit);
3355
3356
assert!(matches!(
3357
data,
3358
MyOuter(external_crate::TheirOuter::<i32>::Unit)
3359
));
3360
data.apply(&patch);
3361
assert!(matches!(
3362
data,
3363
MyOuter(external_crate::TheirOuter::Struct {
3364
value: external_crate::TheirInner::Tuple(123)
3365
})
3366
));
3367
}
3368
3369
#[test]
3370
fn should_take_remote_type() {
3371
mod external_crate {
3372
use alloc::string::String;
3373
3374
#[derive(Debug, Default, PartialEq, Eq)]
3375
pub struct TheirType {
3376
pub value: String,
3377
}
3378
}
3379
3380
// === Remote Wrapper === //
3381
#[reflect_remote(external_crate::TheirType)]
3382
#[derive(Debug, Default)]
3383
#[reflect(Debug, Default)]
3384
struct MyType {
3385
pub value: String,
3386
}
3387
3388
let input: Box<dyn Reflect> = Box::new(MyType(external_crate::TheirType {
3389
value: "Hello".to_string(),
3390
}));
3391
3392
let output: external_crate::TheirType = input
3393
.take()
3394
.expect("should downcast to `external_crate::TheirType`");
3395
assert_eq!(
3396
external_crate::TheirType {
3397
value: "Hello".to_string(),
3398
},
3399
output
3400
);
3401
}
3402
3403
#[test]
3404
fn should_try_take_remote_type() {
3405
mod external_crate {
3406
use alloc::string::String;
3407
3408
#[derive(Debug, Default, PartialEq, Eq)]
3409
pub struct TheirType {
3410
pub value: String,
3411
}
3412
}
3413
3414
// === Remote Wrapper === //
3415
#[reflect_remote(external_crate::TheirType)]
3416
#[derive(Debug, Default)]
3417
#[reflect(Debug, Default)]
3418
struct MyType {
3419
pub value: String,
3420
}
3421
3422
let input: Box<dyn PartialReflect> = Box::new(MyType(external_crate::TheirType {
3423
value: "Hello".to_string(),
3424
}));
3425
3426
let output: external_crate::TheirType = input
3427
.try_take()
3428
.expect("should downcast to `external_crate::TheirType`");
3429
assert_eq!(
3430
external_crate::TheirType {
3431
value: "Hello".to_string(),
3432
},
3433
output,
3434
);
3435
}
3436
3437
#[test]
3438
fn should_take_nested_remote_type() {
3439
mod external_crate {
3440
#[derive(PartialEq, Eq, Debug)]
3441
pub struct TheirOuter<T> {
3442
pub inner: TheirInner<T>,
3443
}
3444
#[derive(PartialEq, Eq, Debug)]
3445
pub struct TheirInner<T>(pub T);
3446
}
3447
3448
#[reflect_remote(external_crate::TheirOuter<T>)]
3449
struct MyOuter<T: FromReflect + Reflectable> {
3450
#[reflect(remote = MyInner<T>)]
3451
pub inner: external_crate::TheirInner<T>,
3452
}
3453
3454
#[reflect_remote(external_crate::TheirInner<T>)]
3455
struct MyInner<T: FromReflect>(pub T);
3456
3457
let input: Box<dyn Reflect> = Box::new(MyOuter(external_crate::TheirOuter {
3458
inner: external_crate::TheirInner(123),
3459
}));
3460
3461
let output: external_crate::TheirOuter<i32> = input
3462
.take()
3463
.expect("should downcast to `external_crate::TheirOuter`");
3464
assert_eq!(
3465
external_crate::TheirOuter {
3466
inner: external_crate::TheirInner(123),
3467
},
3468
output
3469
);
3470
}
3471
3472
// https://github.com/bevyengine/bevy/issues/19017
3473
#[test]
3474
fn should_serialize_opaque_remote_type() {
3475
mod external_crate {
3476
use serde::{Deserialize, Serialize};
3477
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
3478
pub struct Vector2<T>(pub [T; 2]);
3479
}
3480
3481
#[reflect_remote(external_crate::Vector2<i32>)]
3482
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
3483
#[reflect(Serialize, Deserialize)]
3484
#[reflect(opaque)]
3485
struct Vector2Wrapper([i32; 2]);
3486
3487
#[derive(Reflect, Debug, PartialEq)]
3488
struct Point(#[reflect(remote = Vector2Wrapper)] external_crate::Vector2<i32>);
3489
3490
let point = Point(external_crate::Vector2([1, 2]));
3491
3492
let mut registry = TypeRegistry::new();
3493
registry.register::<Point>();
3494
registry.register::<Vector2Wrapper>();
3495
3496
let serializer = ReflectSerializer::new(&point, &registry);
3497
let serialized = ron::to_string(&serializer).unwrap();
3498
assert_eq!(serialized, r#"{"bevy_reflect::tests::Point":((((1,2))))}"#);
3499
3500
let mut deserializer = Deserializer::from_str(&serialized).unwrap();
3501
let reflect_deserializer = ReflectDeserializer::new(&registry);
3502
let deserialized = reflect_deserializer.deserialize(&mut deserializer).unwrap();
3503
let point = <Point as FromReflect>::from_reflect(&*deserialized).unwrap();
3504
assert_eq!(point, Point(external_crate::Vector2([1, 2])));
3505
}
3506
3507
#[cfg(feature = "auto_register")]
3508
mod auto_register_reflect {
3509
use super::*;
3510
3511
#[test]
3512
fn should_ignore_auto_reflect_registration() {
3513
#[derive(Reflect)]
3514
#[reflect(no_auto_register)]
3515
struct NoAutomaticStruct {
3516
a: usize,
3517
}
3518
3519
let mut registry = TypeRegistry::default();
3520
registry.register_derived_types();
3521
3522
assert!(!registry.contains(TypeId::of::<NoAutomaticStruct>()));
3523
}
3524
3525
#[test]
3526
fn should_auto_register_reflect_for_all_supported_types() {
3527
// Struct
3528
#[derive(Reflect)]
3529
struct StructReflect {
3530
a: usize,
3531
}
3532
3533
// ZST struct
3534
#[derive(Reflect)]
3535
struct ZSTStructReflect;
3536
3537
// Tuple struct
3538
#[derive(Reflect)]
3539
struct TupleStructReflect(pub u32);
3540
3541
// Enum
3542
#[derive(Reflect)]
3543
enum EnumReflect {
3544
A,
3545
B,
3546
}
3547
3548
// ZST enum
3549
#[derive(Reflect)]
3550
enum ZSTEnumReflect {}
3551
3552
// Opaque struct
3553
#[derive(Reflect, Clone)]
3554
#[reflect(opaque)]
3555
struct OpaqueStructReflect {
3556
_a: usize,
3557
}
3558
3559
// ZST opaque struct
3560
#[derive(Reflect, Clone)]
3561
#[reflect(opaque)]
3562
struct ZSTOpaqueStructReflect;
3563
3564
let mut registry = TypeRegistry::default();
3565
registry.register_derived_types();
3566
3567
assert!(registry.contains(TypeId::of::<StructReflect>()));
3568
assert!(registry.contains(TypeId::of::<ZSTStructReflect>()));
3569
assert!(registry.contains(TypeId::of::<TupleStructReflect>()));
3570
assert!(registry.contains(TypeId::of::<EnumReflect>()));
3571
assert!(registry.contains(TypeId::of::<ZSTEnumReflect>()));
3572
assert!(registry.contains(TypeId::of::<OpaqueStructReflect>()));
3573
assert!(registry.contains(TypeId::of::<ZSTOpaqueStructReflect>()));
3574
}
3575
}
3576
3577
#[cfg(feature = "glam")]
3578
mod glam {
3579
use super::*;
3580
use ::glam::{quat, vec3, Quat, Vec3};
3581
3582
#[test]
3583
fn quat_serialization() {
3584
let q = quat(1.0, 2.0, 3.0, 4.0);
3585
3586
let mut registry = TypeRegistry::default();
3587
registry.register::<f32>();
3588
registry.register::<Quat>();
3589
3590
let ser = ReflectSerializer::new(&q, &registry);
3591
3592
let config = PrettyConfig::default()
3593
.new_line(String::from("\n"))
3594
.indentor(String::from(" "));
3595
let output = to_string_pretty(&ser, config).unwrap();
3596
let expected = r#"
3597
{
3598
"glam::Quat": (1.0, 2.0, 3.0, 4.0),
3599
}"#;
3600
3601
assert_eq!(expected, format!("\n{output}"));
3602
}
3603
3604
#[test]
3605
fn quat_deserialization() {
3606
let data = r#"
3607
{
3608
"glam::Quat": (1.0, 2.0, 3.0, 4.0),
3609
}"#;
3610
3611
let mut registry = TypeRegistry::default();
3612
registry.register::<Quat>();
3613
registry.register::<f32>();
3614
3615
let de = ReflectDeserializer::new(&registry);
3616
3617
let mut deserializer =
3618
Deserializer::from_str(data).expect("Failed to acquire deserializer");
3619
3620
let dynamic_struct = de
3621
.deserialize(&mut deserializer)
3622
.expect("Failed to deserialize");
3623
3624
let mut result = Quat::default();
3625
3626
result.apply(dynamic_struct.as_partial_reflect());
3627
3628
assert_eq!(result, quat(1.0, 2.0, 3.0, 4.0));
3629
}
3630
3631
#[test]
3632
fn vec3_serialization() {
3633
let v = vec3(12.0, 3.0, -6.9);
3634
3635
let mut registry = TypeRegistry::default();
3636
registry.register::<f32>();
3637
registry.register::<Vec3>();
3638
3639
let ser = ReflectSerializer::new(&v, &registry);
3640
3641
let config = PrettyConfig::default()
3642
.new_line(String::from("\n"))
3643
.indentor(String::from(" "));
3644
let output = to_string_pretty(&ser, config).unwrap();
3645
let expected = r#"
3646
{
3647
"glam::Vec3": (12.0, 3.0, -6.9),
3648
}"#;
3649
3650
assert_eq!(expected, format!("\n{output}"));
3651
}
3652
3653
#[test]
3654
fn vec3_deserialization() {
3655
let data = r#"
3656
{
3657
"glam::Vec3": (12.0, 3.0, -6.9),
3658
}"#;
3659
3660
let mut registry = TypeRegistry::default();
3661
registry.add_registration(Vec3::get_type_registration());
3662
registry.add_registration(f32::get_type_registration());
3663
3664
let de = ReflectDeserializer::new(&registry);
3665
3666
let mut deserializer =
3667
Deserializer::from_str(data).expect("Failed to acquire deserializer");
3668
3669
let dynamic_struct = de
3670
.deserialize(&mut deserializer)
3671
.expect("Failed to deserialize");
3672
3673
let mut result = Vec3::default();
3674
3675
result.apply(dynamic_struct.as_partial_reflect());
3676
3677
assert_eq!(result, vec3(12.0, 3.0, -6.9));
3678
}
3679
3680
#[test]
3681
fn vec3_field_access() {
3682
let mut v = vec3(1.0, 2.0, 3.0);
3683
3684
assert_eq!(*v.get_field::<f32>("x").unwrap(), 1.0);
3685
3686
*v.get_field_mut::<f32>("y").unwrap() = 6.0;
3687
3688
assert_eq!(v.y, 6.0);
3689
}
3690
3691
#[test]
3692
fn vec3_path_access() {
3693
let mut v = vec3(1.0, 2.0, 3.0);
3694
3695
assert_eq!(
3696
*v.reflect_path("x")
3697
.unwrap()
3698
.try_downcast_ref::<f32>()
3699
.unwrap(),
3700
1.0
3701
);
3702
3703
*v.reflect_path_mut("y")
3704
.unwrap()
3705
.try_downcast_mut::<f32>()
3706
.unwrap() = 6.0;
3707
3708
assert_eq!(v.y, 6.0);
3709
}
3710
3711
#[test]
3712
fn vec3_apply_dynamic() {
3713
let mut v = vec3(3.0, 3.0, 3.0);
3714
3715
let mut d = DynamicStruct::default();
3716
d.insert("x", 4.0f32);
3717
d.insert("y", 2.0f32);
3718
d.insert("z", 1.0f32);
3719
3720
v.apply(&d);
3721
3722
assert_eq!(v, vec3(4.0, 2.0, 1.0));
3723
}
3724
}
3725
}
3726
3727