Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_reflect/src/lib.rs
6849 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 is;
587
mod kind;
588
mod list;
589
mod map;
590
mod path;
591
mod reflect;
592
mod reflectable;
593
mod remote;
594
mod set;
595
mod struct_trait;
596
mod tuple;
597
mod tuple_struct;
598
mod type_info;
599
mod type_path;
600
mod type_registry;
601
602
mod impls {
603
mod alloc;
604
mod bevy_platform;
605
mod core;
606
mod foldhash;
607
#[cfg(feature = "hashbrown")]
608
mod hashbrown;
609
mod macros;
610
#[cfg(feature = "std")]
611
mod std;
612
613
#[cfg(feature = "glam")]
614
mod glam;
615
#[cfg(feature = "petgraph")]
616
mod petgraph;
617
#[cfg(feature = "smallvec")]
618
mod smallvec;
619
#[cfg(feature = "smol_str")]
620
mod smol_str;
621
#[cfg(feature = "uuid")]
622
mod uuid;
623
#[cfg(feature = "wgpu-types")]
624
mod wgpu_types;
625
}
626
627
pub mod attributes;
628
mod enums;
629
mod generics;
630
pub mod serde;
631
pub mod std_traits;
632
#[cfg(feature = "debug_stack")]
633
mod type_info_stack;
634
pub mod utility;
635
636
/// The reflect prelude.
637
///
638
/// This includes the most common types in this crate, re-exported for your convenience.
639
pub mod prelude {
640
pub use crate::std_traits::*;
641
642
#[doc(hidden)]
643
pub use crate::{
644
reflect_trait, FromReflect, GetField, GetPath, GetTupleStructField, PartialReflect,
645
Reflect, ReflectDeserialize, ReflectFromReflect, ReflectPath, ReflectSerialize, Struct,
646
TupleStruct, TypePath,
647
};
648
649
#[cfg(feature = "functions")]
650
pub use crate::func::{Function, IntoFunction, IntoFunctionMut};
651
}
652
653
pub use array::*;
654
pub use enums::*;
655
pub use error::*;
656
pub use fields::*;
657
pub use from_reflect::*;
658
pub use generics::*;
659
pub use is::*;
660
pub use kind::*;
661
pub use list::*;
662
pub use map::*;
663
pub use path::*;
664
pub use reflect::*;
665
pub use reflectable::*;
666
pub use remote::*;
667
pub use set::*;
668
pub use struct_trait::*;
669
pub use tuple::*;
670
pub use tuple_struct::*;
671
pub use type_info::*;
672
pub use type_path::*;
673
pub use type_registry::*;
674
675
pub use bevy_reflect_derive::*;
676
pub use erased_serde;
677
678
/// Exports used by the reflection macros.
679
///
680
/// These are not meant to be used directly and are subject to breaking changes.
681
#[doc(hidden)]
682
pub mod __macro_exports {
683
use crate::{
684
DynamicArray, DynamicEnum, DynamicList, DynamicMap, DynamicStruct, DynamicTuple,
685
DynamicTupleStruct, GetTypeRegistration, TypeRegistry,
686
};
687
688
/// Re-exports of items from the [`alloc`] crate.
689
///
690
/// This is required because in `std` environments (e.g., the `std` feature is enabled)
691
/// the `alloc` crate may not have been included, making its namespace unreliable.
692
pub mod alloc_utils {
693
pub use ::alloc::{
694
borrow::{Cow, ToOwned},
695
boxed::Box,
696
string::ToString,
697
};
698
}
699
700
/// A wrapper trait around [`GetTypeRegistration`].
701
///
702
/// This trait is used by the derive macro to recursively register all type dependencies.
703
/// It's used instead of `GetTypeRegistration` directly to avoid making dynamic types also
704
/// implement `GetTypeRegistration` in order to be used as active fields.
705
///
706
/// This trait has a blanket implementation for all types that implement `GetTypeRegistration`
707
/// and manual implementations for all dynamic types (which simply do nothing).
708
#[diagnostic::on_unimplemented(
709
message = "`{Self}` does not implement `GetTypeRegistration` so cannot be registered for reflection",
710
note = "consider annotating `{Self}` with `#[derive(Reflect)]`"
711
)]
712
pub trait RegisterForReflection {
713
#[expect(
714
unused_variables,
715
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."
716
)]
717
fn __register(registry: &mut TypeRegistry) {}
718
}
719
720
impl<T: GetTypeRegistration> RegisterForReflection for T {
721
fn __register(registry: &mut TypeRegistry) {
722
registry.register::<T>();
723
}
724
}
725
726
impl RegisterForReflection for DynamicEnum {}
727
728
impl RegisterForReflection for DynamicTupleStruct {}
729
730
impl RegisterForReflection for DynamicStruct {}
731
732
impl RegisterForReflection for DynamicMap {}
733
734
impl RegisterForReflection for DynamicList {}
735
736
impl RegisterForReflection for DynamicArray {}
737
738
impl RegisterForReflection for DynamicTuple {}
739
740
/// Automatic reflect registration implementation
741
#[cfg(feature = "auto_register")]
742
pub mod auto_register {
743
pub use super::*;
744
745
#[cfg(all(
746
not(feature = "auto_register_inventory"),
747
not(feature = "auto_register_static")
748
))]
749
compile_error!(
750
"Choosing a backend is required for automatic reflect registration. Please enable either the \"auto_register_inventory\" or the \"auto_register_static\" feature."
751
);
752
753
/// inventory impl
754
#[cfg(all(
755
not(feature = "auto_register_static"),
756
feature = "auto_register_inventory"
757
))]
758
mod __automatic_type_registration_impl {
759
use super::*;
760
761
pub use inventory;
762
763
/// Stores type registration functions
764
pub struct AutomaticReflectRegistrations(pub fn(&mut TypeRegistry));
765
766
/// Registers all collected types.
767
pub fn register_types(registry: &mut TypeRegistry) {
768
#[cfg(target_family = "wasm")]
769
wasm_support::init();
770
for registration_fn in inventory::iter::<AutomaticReflectRegistrations> {
771
registration_fn.0(registry);
772
}
773
}
774
775
inventory::collect!(AutomaticReflectRegistrations);
776
777
#[cfg(target_family = "wasm")]
778
mod wasm_support {
779
use bevy_platform::sync::atomic::{AtomicBool, Ordering};
780
781
static INIT_DONE: AtomicBool = AtomicBool::new(false);
782
783
#[expect(unsafe_code, reason = "This function is generated by linker.")]
784
unsafe extern "C" {
785
fn __wasm_call_ctors();
786
}
787
788
/// This function must be called before using [`inventory::iter`] on [`AutomaticReflectRegistrations`] to run constructors on all platforms.
789
pub fn init() {
790
if INIT_DONE.swap(true, Ordering::Relaxed) {
791
return;
792
};
793
// SAFETY:
794
// This will call constructors on wasm platforms at most once (as long as `init` is the only function that calls `__wasm_call_ctors`).
795
//
796
// For more information see: https://docs.rs/inventory/latest/inventory/#webassembly-and-constructors
797
#[expect(
798
unsafe_code,
799
reason = "This function must be called to use inventory on wasm."
800
)]
801
unsafe {
802
__wasm_call_ctors();
803
}
804
}
805
}
806
}
807
808
/// static impl
809
#[cfg(feature = "auto_register_static")]
810
mod __automatic_type_registration_impl {
811
use super::*;
812
use alloc::vec::Vec;
813
use bevy_platform::sync::Mutex;
814
815
static REGISTRATION_FNS: Mutex<Vec<fn(&mut TypeRegistry)>> = Mutex::new(Vec::new());
816
817
/// Adds adds a new registration function for [`TypeRegistry`]
818
pub fn push_registration_fn(registration_fn: fn(&mut TypeRegistry)) {
819
REGISTRATION_FNS.lock().unwrap().push(registration_fn);
820
}
821
822
/// Registers all collected types.
823
pub fn register_types(registry: &mut TypeRegistry) {
824
for func in REGISTRATION_FNS.lock().unwrap().iter() {
825
(func)(registry);
826
}
827
}
828
}
829
830
#[cfg(any(feature = "auto_register_static", feature = "auto_register_inventory"))]
831
pub use __automatic_type_registration_impl::*;
832
}
833
}
834
835
#[cfg(test)]
836
#[expect(
837
clippy::approx_constant,
838
reason = "We don't need the exact value of Pi here."
839
)]
840
mod tests {
841
use ::serde::{de::DeserializeSeed, Deserialize, Serialize};
842
use alloc::{
843
borrow::Cow,
844
boxed::Box,
845
format,
846
string::{String, ToString},
847
vec,
848
vec::Vec,
849
};
850
use bevy_platform::collections::HashMap;
851
use core::{
852
any::TypeId,
853
fmt::{Debug, Formatter},
854
hash::Hash,
855
marker::PhantomData,
856
};
857
use disqualified::ShortName;
858
use ron::{
859
ser::{to_string_pretty, PrettyConfig},
860
Deserializer,
861
};
862
use static_assertions::{assert_impl_all, assert_not_impl_all};
863
864
use super::{prelude::*, *};
865
use crate::{
866
serde::{ReflectDeserializer, ReflectSerializer},
867
utility::GenericTypePathCell,
868
};
869
870
#[test]
871
fn try_apply_should_detect_kinds() {
872
#[derive(Reflect, Debug)]
873
struct Struct {
874
a: u32,
875
b: f32,
876
}
877
878
#[derive(Reflect, Debug)]
879
enum Enum {
880
A,
881
B(u32),
882
}
883
884
let mut struct_target = Struct {
885
a: 0xDEADBEEF,
886
b: 3.14,
887
};
888
889
let mut enum_target = Enum::A;
890
891
let array_src = [8, 0, 8];
892
893
let result = struct_target.try_apply(&enum_target);
894
assert!(
895
matches!(
896
result,
897
Err(ApplyError::MismatchedKinds {
898
from_kind: ReflectKind::Enum,
899
to_kind: ReflectKind::Struct
900
})
901
),
902
"result was {result:?}"
903
);
904
905
let result = enum_target.try_apply(&array_src);
906
assert!(
907
matches!(
908
result,
909
Err(ApplyError::MismatchedKinds {
910
from_kind: ReflectKind::Array,
911
to_kind: ReflectKind::Enum
912
})
913
),
914
"result was {result:?}"
915
);
916
}
917
918
#[test]
919
fn reflect_struct() {
920
#[derive(Reflect)]
921
struct Foo {
922
a: u32,
923
b: f32,
924
c: Bar,
925
}
926
#[derive(Reflect)]
927
struct Bar {
928
x: u32,
929
}
930
931
let mut foo = Foo {
932
a: 42,
933
b: 3.14,
934
c: Bar { x: 1 },
935
};
936
937
let a = *foo.get_field::<u32>("a").unwrap();
938
assert_eq!(a, 42);
939
940
*foo.get_field_mut::<u32>("a").unwrap() += 1;
941
assert_eq!(foo.a, 43);
942
943
let bar = foo.get_field::<Bar>("c").unwrap();
944
assert_eq!(bar.x, 1);
945
946
// nested retrieval
947
let c = foo.field("c").unwrap();
948
let value = c.reflect_ref().as_struct().unwrap();
949
assert_eq!(*value.get_field::<u32>("x").unwrap(), 1);
950
951
// patch Foo with a dynamic struct
952
let mut dynamic_struct = DynamicStruct::default();
953
dynamic_struct.insert("a", 123u32);
954
dynamic_struct.insert("should_be_ignored", 456);
955
956
foo.apply(&dynamic_struct);
957
assert_eq!(foo.a, 123);
958
}
959
960
#[test]
961
fn reflect_map() {
962
#[derive(Reflect, Hash)]
963
#[reflect(Hash)]
964
struct Foo {
965
a: u32,
966
b: String,
967
}
968
969
let key_a = Foo {
970
a: 1,
971
b: "k1".to_string(),
972
};
973
974
let key_b = Foo {
975
a: 1,
976
b: "k1".to_string(),
977
};
978
979
let key_c = Foo {
980
a: 3,
981
b: "k3".to_string(),
982
};
983
984
let mut map = DynamicMap::default();
985
map.insert(key_a, 10u32);
986
assert_eq!(
987
10,
988
*map.get(&key_b).unwrap().try_downcast_ref::<u32>().unwrap()
989
);
990
assert!(map.get(&key_c).is_none());
991
*map.get_mut(&key_b)
992
.unwrap()
993
.try_downcast_mut::<u32>()
994
.unwrap() = 20;
995
assert_eq!(
996
20,
997
*map.get(&key_b).unwrap().try_downcast_ref::<u32>().unwrap()
998
);
999
}
1000
1001
#[test]
1002
fn reflect_unit_struct() {
1003
#[derive(Reflect)]
1004
struct Foo(u32, u64);
1005
1006
let mut foo = Foo(1, 2);
1007
assert_eq!(1, *foo.get_field::<u32>(0).unwrap());
1008
assert_eq!(2, *foo.get_field::<u64>(1).unwrap());
1009
1010
let mut patch = DynamicTupleStruct::default();
1011
patch.insert(3u32);
1012
patch.insert(4u64);
1013
assert_eq!(
1014
3,
1015
*patch.field(0).unwrap().try_downcast_ref::<u32>().unwrap()
1016
);
1017
assert_eq!(
1018
4,
1019
*patch.field(1).unwrap().try_downcast_ref::<u64>().unwrap()
1020
);
1021
1022
foo.apply(&patch);
1023
assert_eq!(3, foo.0);
1024
assert_eq!(4, foo.1);
1025
1026
let mut iter = patch.iter_fields();
1027
assert_eq!(3, *iter.next().unwrap().try_downcast_ref::<u32>().unwrap());
1028
assert_eq!(4, *iter.next().unwrap().try_downcast_ref::<u64>().unwrap());
1029
}
1030
1031
#[test]
1032
#[should_panic(
1033
expected = "the given key of type `bevy_reflect::tests::Foo` does not support hashing"
1034
)]
1035
fn reflect_map_no_hash() {
1036
#[derive(Reflect)]
1037
struct Foo {
1038
a: u32,
1039
}
1040
1041
let foo = Foo { a: 1 };
1042
assert!(foo.reflect_hash().is_none());
1043
1044
let mut map = DynamicMap::default();
1045
map.insert(foo, 10u32);
1046
}
1047
1048
#[test]
1049
#[should_panic(
1050
expected = "the dynamic type `bevy_reflect::DynamicStruct` (representing `bevy_reflect::tests::Foo`) does not support hashing"
1051
)]
1052
fn reflect_map_no_hash_dynamic_representing() {
1053
#[derive(Reflect, Hash)]
1054
#[reflect(Hash)]
1055
struct Foo {
1056
a: u32,
1057
}
1058
1059
let foo = Foo { a: 1 };
1060
assert!(foo.reflect_hash().is_some());
1061
let dynamic = foo.to_dynamic_struct();
1062
1063
let mut map = DynamicMap::default();
1064
map.insert(dynamic, 11u32);
1065
}
1066
1067
#[test]
1068
#[should_panic(
1069
expected = "the dynamic type `bevy_reflect::DynamicStruct` does not support hashing"
1070
)]
1071
fn reflect_map_no_hash_dynamic() {
1072
#[allow(
1073
clippy::allow_attributes,
1074
dead_code,
1075
reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
1076
)]
1077
#[derive(Reflect, Hash)]
1078
#[reflect(Hash)]
1079
struct Foo {
1080
a: u32,
1081
}
1082
1083
let mut dynamic = DynamicStruct::default();
1084
dynamic.insert("a", 4u32);
1085
assert!(dynamic.reflect_hash().is_none());
1086
1087
let mut map = DynamicMap::default();
1088
map.insert(dynamic, 11u32);
1089
}
1090
1091
#[test]
1092
fn reflect_ignore() {
1093
#[derive(Reflect)]
1094
struct Foo {
1095
a: u32,
1096
#[reflect(ignore)]
1097
_b: u32,
1098
}
1099
1100
let foo = Foo { a: 1, _b: 2 };
1101
1102
let values: Vec<u32> = foo
1103
.iter_fields()
1104
.map(|value| *value.try_downcast_ref::<u32>().unwrap())
1105
.collect();
1106
assert_eq!(values, vec![1]);
1107
}
1108
1109
/// This test ensures that we are able to reflect generic types with one or more type parameters.
1110
///
1111
/// When there is an `Add` implementation for `String`, the compiler isn't able to infer the correct
1112
/// type to deref to.
1113
/// If we don't append the strings in the `TypePath` derive correctly (i.e. explicitly specifying the type),
1114
/// we'll get a compilation error saying that "`&String` cannot be added to `String`".
1115
///
1116
/// So this test just ensures that we do that correctly.
1117
///
1118
/// This problem is a known issue and is unexpectedly expected behavior:
1119
/// - <https://github.com/rust-lang/rust/issues/77143>
1120
/// - <https://github.com/bodil/smartstring/issues/7>
1121
/// - <https://github.com/pola-rs/polars/issues/14666>
1122
#[test]
1123
fn should_reflect_generic() {
1124
struct FakeString {}
1125
1126
// This implementation confuses the compiler when trying to add a `&String` to a `String`
1127
impl core::ops::Add<FakeString> for String {
1128
type Output = Self;
1129
fn add(self, _rhs: FakeString) -> Self::Output {
1130
unreachable!()
1131
}
1132
}
1133
1134
#[expect(
1135
dead_code,
1136
reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
1137
)]
1138
#[derive(Reflect)]
1139
struct Foo<A>(A);
1140
1141
#[expect(
1142
dead_code,
1143
reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
1144
)]
1145
#[derive(Reflect)]
1146
struct Bar<A, B>(A, B);
1147
1148
#[expect(
1149
dead_code,
1150
reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
1151
)]
1152
#[derive(Reflect)]
1153
struct Baz<A, B, C>(A, B, C);
1154
}
1155
1156
#[test]
1157
fn should_reflect_clone() {
1158
// Struct
1159
#[derive(Reflect, Debug, PartialEq)]
1160
struct Foo(usize);
1161
1162
let value = Foo(123);
1163
let clone = value.reflect_clone().expect("should reflect_clone struct");
1164
assert_eq!(value, clone.take::<Foo>().unwrap());
1165
1166
// Tuple
1167
let foo = (123, 4.56);
1168
let clone = foo.reflect_clone().expect("should reflect_clone tuple");
1169
assert_eq!(foo, clone.take::<(u32, f32)>().unwrap());
1170
}
1171
1172
#[test]
1173
fn should_reflect_clone_generic_type() {
1174
#[derive(Reflect, Debug, PartialEq)]
1175
struct Foo<T, U>(T, #[reflect(ignore, clone)] PhantomData<U>);
1176
#[derive(TypePath, Debug, PartialEq)]
1177
struct Bar;
1178
1179
// `usize` will be cloned via `Reflect::reflect_clone`
1180
// `PhantomData<Bar>` will be cloned via `Clone::clone`
1181
let value = Foo::<usize, Bar>(123, PhantomData);
1182
let clone = value
1183
.reflect_clone()
1184
.expect("should reflect_clone generic struct");
1185
assert_eq!(value, clone.take::<Foo<usize, Bar>>().unwrap());
1186
}
1187
1188
#[test]
1189
fn should_reflect_clone_with_clone() {
1190
// A custom clone function to verify that the `#[reflect(Clone)]` container attribute
1191
// takes precedence over the `#[reflect(clone)]` field attribute.
1192
#[expect(
1193
dead_code,
1194
reason = "if things are working correctly, this function should never be called"
1195
)]
1196
fn custom_clone(_value: &usize) -> usize {
1197
panic!("should not be called");
1198
}
1199
1200
// Tuple Struct
1201
#[derive(Reflect, Clone, Debug, PartialEq)]
1202
#[reflect(Clone)]
1203
struct Foo(#[reflect(clone = "custom_clone")] usize);
1204
1205
let value = Foo(123);
1206
let clone = value
1207
.reflect_clone()
1208
.expect("should reflect_clone tuple struct");
1209
assert_eq!(value, clone.take::<Foo>().unwrap());
1210
1211
// Struct
1212
#[derive(Reflect, Clone, Debug, PartialEq)]
1213
#[reflect(Clone)]
1214
struct Bar {
1215
#[reflect(clone = "custom_clone")]
1216
value: usize,
1217
}
1218
1219
let value = Bar { value: 123 };
1220
let clone = value.reflect_clone().expect("should reflect_clone struct");
1221
assert_eq!(value, clone.take::<Bar>().unwrap());
1222
1223
// Enum
1224
#[derive(Reflect, Clone, Debug, PartialEq)]
1225
#[reflect(Clone)]
1226
enum Baz {
1227
Unit,
1228
Tuple(#[reflect(clone = "custom_clone")] usize),
1229
Struct {
1230
#[reflect(clone = "custom_clone")]
1231
value: usize,
1232
},
1233
}
1234
1235
let value = Baz::Unit;
1236
let clone = value
1237
.reflect_clone()
1238
.expect("should reflect_clone unit variant");
1239
assert_eq!(value, clone.take::<Baz>().unwrap());
1240
1241
let value = Baz::Tuple(123);
1242
let clone = value
1243
.reflect_clone()
1244
.expect("should reflect_clone tuple variant");
1245
assert_eq!(value, clone.take::<Baz>().unwrap());
1246
1247
let value = Baz::Struct { value: 123 };
1248
let clone = value
1249
.reflect_clone()
1250
.expect("should reflect_clone struct variant");
1251
assert_eq!(value, clone.take::<Baz>().unwrap());
1252
}
1253
1254
#[test]
1255
fn should_custom_reflect_clone() {
1256
#[derive(Reflect, Debug, PartialEq)]
1257
#[reflect(Clone(clone_foo))]
1258
struct Foo(usize);
1259
1260
fn clone_foo(foo: &Foo) -> Foo {
1261
Foo(foo.0 + 198)
1262
}
1263
1264
let foo = Foo(123);
1265
let clone = foo.reflect_clone().unwrap();
1266
assert_eq!(Foo(321), clone.take::<Foo>().unwrap());
1267
}
1268
1269
#[test]
1270
fn should_not_clone_ignored_fields() {
1271
// Tuple Struct
1272
#[derive(Reflect, Clone, Debug, PartialEq)]
1273
struct Foo(#[reflect(ignore)] usize);
1274
1275
let foo = Foo(123);
1276
let clone = foo.reflect_clone();
1277
assert_eq!(
1278
clone.unwrap_err(),
1279
ReflectCloneError::FieldNotCloneable {
1280
field: FieldId::Unnamed(0),
1281
variant: None,
1282
container_type_path: Cow::Borrowed(Foo::type_path()),
1283
}
1284
);
1285
1286
// Struct
1287
#[derive(Reflect, Clone, Debug, PartialEq)]
1288
struct Bar {
1289
#[reflect(ignore)]
1290
value: usize,
1291
}
1292
1293
let bar = Bar { value: 123 };
1294
let clone = bar.reflect_clone();
1295
assert_eq!(
1296
clone.unwrap_err(),
1297
ReflectCloneError::FieldNotCloneable {
1298
field: FieldId::Named(Cow::Borrowed("value")),
1299
variant: None,
1300
container_type_path: Cow::Borrowed(Bar::type_path()),
1301
}
1302
);
1303
1304
// Enum
1305
#[derive(Reflect, Clone, Debug, PartialEq)]
1306
enum Baz {
1307
Tuple(#[reflect(ignore)] usize),
1308
Struct {
1309
#[reflect(ignore)]
1310
value: usize,
1311
},
1312
}
1313
1314
let baz = Baz::Tuple(123);
1315
let clone = baz.reflect_clone();
1316
assert_eq!(
1317
clone.unwrap_err(),
1318
ReflectCloneError::FieldNotCloneable {
1319
field: FieldId::Unnamed(0),
1320
variant: Some(Cow::Borrowed("Tuple")),
1321
container_type_path: Cow::Borrowed(Baz::type_path()),
1322
}
1323
);
1324
1325
let baz = Baz::Struct { value: 123 };
1326
let clone = baz.reflect_clone();
1327
assert_eq!(
1328
clone.unwrap_err(),
1329
ReflectCloneError::FieldNotCloneable {
1330
field: FieldId::Named(Cow::Borrowed("value")),
1331
variant: Some(Cow::Borrowed("Struct")),
1332
container_type_path: Cow::Borrowed(Baz::type_path()),
1333
}
1334
);
1335
}
1336
1337
#[test]
1338
fn should_clone_ignored_fields_with_clone_attributes() {
1339
#[derive(Reflect, Clone, Debug, PartialEq)]
1340
struct Foo(#[reflect(ignore, clone)] usize);
1341
1342
let foo = Foo(123);
1343
let clone = foo.reflect_clone().unwrap();
1344
assert_eq!(Foo(123), clone.take::<Foo>().unwrap());
1345
1346
#[derive(Reflect, Clone, Debug, PartialEq)]
1347
struct Bar(#[reflect(ignore, clone = "clone_usize")] usize);
1348
1349
fn clone_usize(this: &usize) -> usize {
1350
*this + 198
1351
}
1352
1353
let bar = Bar(123);
1354
let clone = bar.reflect_clone().unwrap();
1355
assert_eq!(Bar(321), clone.take::<Bar>().unwrap());
1356
}
1357
1358
#[test]
1359
fn should_composite_reflect_clone() {
1360
#[derive(Reflect, Debug, PartialEq)]
1361
enum MyEnum {
1362
Unit,
1363
Tuple(
1364
Foo,
1365
#[reflect(ignore, clone)] Bar,
1366
#[reflect(clone = "clone_baz")] Baz,
1367
),
1368
Struct {
1369
foo: Foo,
1370
#[reflect(ignore, clone)]
1371
bar: Bar,
1372
#[reflect(clone = "clone_baz")]
1373
baz: Baz,
1374
},
1375
}
1376
1377
#[derive(Reflect, Debug, PartialEq)]
1378
struct Foo {
1379
#[reflect(clone = "clone_bar")]
1380
bar: Bar,
1381
baz: Baz,
1382
}
1383
1384
#[derive(Reflect, Default, Clone, Debug, PartialEq)]
1385
#[reflect(Clone)]
1386
struct Bar(String);
1387
1388
#[derive(Reflect, Debug, PartialEq)]
1389
struct Baz(String);
1390
1391
fn clone_bar(bar: &Bar) -> Bar {
1392
Bar(format!("{}!", bar.0))
1393
}
1394
1395
fn clone_baz(baz: &Baz) -> Baz {
1396
Baz(format!("{}!", baz.0))
1397
}
1398
1399
let my_enum = MyEnum::Unit;
1400
let clone = my_enum.reflect_clone().unwrap();
1401
assert_eq!(MyEnum::Unit, clone.take::<MyEnum>().unwrap());
1402
1403
let my_enum = MyEnum::Tuple(
1404
Foo {
1405
bar: Bar("bar".to_string()),
1406
baz: Baz("baz".to_string()),
1407
},
1408
Bar("bar".to_string()),
1409
Baz("baz".to_string()),
1410
);
1411
let clone = my_enum.reflect_clone().unwrap();
1412
assert_eq!(
1413
MyEnum::Tuple(
1414
Foo {
1415
bar: Bar("bar!".to_string()),
1416
baz: Baz("baz".to_string()),
1417
},
1418
Bar("bar".to_string()),
1419
Baz("baz!".to_string()),
1420
),
1421
clone.take::<MyEnum>().unwrap()
1422
);
1423
1424
let my_enum = MyEnum::Struct {
1425
foo: Foo {
1426
bar: Bar("bar".to_string()),
1427
baz: Baz("baz".to_string()),
1428
},
1429
bar: Bar("bar".to_string()),
1430
baz: Baz("baz".to_string()),
1431
};
1432
let clone = my_enum.reflect_clone().unwrap();
1433
assert_eq!(
1434
MyEnum::Struct {
1435
foo: Foo {
1436
bar: Bar("bar!".to_string()),
1437
baz: Baz("baz".to_string()),
1438
},
1439
bar: Bar("bar".to_string()),
1440
baz: Baz("baz!".to_string()),
1441
},
1442
clone.take::<MyEnum>().unwrap()
1443
);
1444
}
1445
1446
#[test]
1447
fn should_call_from_reflect_dynamically() {
1448
#[derive(Reflect)]
1449
struct MyStruct {
1450
foo: usize,
1451
}
1452
1453
// Register
1454
let mut registry = TypeRegistry::default();
1455
registry.register::<MyStruct>();
1456
1457
// Get type data
1458
let type_id = TypeId::of::<MyStruct>();
1459
let rfr = registry
1460
.get_type_data::<ReflectFromReflect>(type_id)
1461
.expect("the FromReflect trait should be registered");
1462
1463
// Call from_reflect
1464
let mut dynamic_struct = DynamicStruct::default();
1465
dynamic_struct.insert("foo", 123usize);
1466
let reflected = rfr
1467
.from_reflect(&dynamic_struct)
1468
.expect("the type should be properly reflected");
1469
1470
// Assert
1471
let expected = MyStruct { foo: 123 };
1472
assert!(expected
1473
.reflect_partial_eq(reflected.as_partial_reflect())
1474
.unwrap_or_default());
1475
let not_expected = MyStruct { foo: 321 };
1476
assert!(!not_expected
1477
.reflect_partial_eq(reflected.as_partial_reflect())
1478
.unwrap_or_default());
1479
}
1480
1481
#[test]
1482
fn from_reflect_should_allow_ignored_unnamed_fields() {
1483
#[derive(Reflect, Eq, PartialEq, Debug)]
1484
struct MyTupleStruct(i8, #[reflect(ignore)] i16, i32);
1485
1486
let expected = MyTupleStruct(1, 0, 3);
1487
1488
let mut dyn_tuple_struct = DynamicTupleStruct::default();
1489
dyn_tuple_struct.insert(1_i8);
1490
dyn_tuple_struct.insert(3_i32);
1491
let my_tuple_struct = <MyTupleStruct as FromReflect>::from_reflect(&dyn_tuple_struct);
1492
1493
assert_eq!(Some(expected), my_tuple_struct);
1494
1495
#[derive(Reflect, Eq, PartialEq, Debug)]
1496
enum MyEnum {
1497
Tuple(i8, #[reflect(ignore)] i16, i32),
1498
}
1499
1500
let expected = MyEnum::Tuple(1, 0, 3);
1501
1502
let mut dyn_tuple = DynamicTuple::default();
1503
dyn_tuple.insert(1_i8);
1504
dyn_tuple.insert(3_i32);
1505
1506
let mut dyn_enum = DynamicEnum::default();
1507
dyn_enum.set_variant("Tuple", dyn_tuple);
1508
1509
let my_enum = <MyEnum as FromReflect>::from_reflect(&dyn_enum);
1510
1511
assert_eq!(Some(expected), my_enum);
1512
}
1513
1514
#[test]
1515
fn from_reflect_should_use_default_field_attributes() {
1516
#[derive(Reflect, Eq, PartialEq, Debug)]
1517
struct MyStruct {
1518
// Use `Default::default()`
1519
// Note that this isn't an ignored field
1520
#[reflect(default)]
1521
foo: String,
1522
1523
// Use `get_bar_default()`
1524
#[reflect(ignore)]
1525
#[reflect(default = "get_bar_default")]
1526
bar: NotReflect,
1527
1528
// Ensure attributes can be combined
1529
#[reflect(ignore, default = "get_bar_default")]
1530
baz: NotReflect,
1531
}
1532
1533
#[derive(Eq, PartialEq, Debug)]
1534
struct NotReflect(usize);
1535
1536
fn get_bar_default() -> NotReflect {
1537
NotReflect(123)
1538
}
1539
1540
let expected = MyStruct {
1541
foo: String::default(),
1542
bar: NotReflect(123),
1543
baz: NotReflect(123),
1544
};
1545
1546
let dyn_struct = DynamicStruct::default();
1547
let my_struct = <MyStruct as FromReflect>::from_reflect(&dyn_struct);
1548
1549
assert_eq!(Some(expected), my_struct);
1550
}
1551
1552
#[test]
1553
fn from_reflect_should_use_default_variant_field_attributes() {
1554
#[derive(Reflect, Eq, PartialEq, Debug)]
1555
enum MyEnum {
1556
Foo(#[reflect(default)] String),
1557
Bar {
1558
#[reflect(default = "get_baz_default")]
1559
#[reflect(ignore)]
1560
baz: usize,
1561
},
1562
}
1563
1564
fn get_baz_default() -> usize {
1565
123
1566
}
1567
1568
let expected = MyEnum::Foo(String::default());
1569
1570
let dyn_enum = DynamicEnum::new("Foo", DynamicTuple::default());
1571
let my_enum = <MyEnum as FromReflect>::from_reflect(&dyn_enum);
1572
1573
assert_eq!(Some(expected), my_enum);
1574
1575
let expected = MyEnum::Bar {
1576
baz: get_baz_default(),
1577
};
1578
1579
let dyn_enum = DynamicEnum::new("Bar", DynamicStruct::default());
1580
let my_enum = <MyEnum as FromReflect>::from_reflect(&dyn_enum);
1581
1582
assert_eq!(Some(expected), my_enum);
1583
}
1584
1585
#[test]
1586
fn from_reflect_should_use_default_container_attribute() {
1587
#[derive(Reflect, Eq, PartialEq, Debug)]
1588
#[reflect(Default)]
1589
struct MyStruct {
1590
foo: String,
1591
#[reflect(ignore)]
1592
bar: usize,
1593
}
1594
1595
impl Default for MyStruct {
1596
fn default() -> Self {
1597
Self {
1598
foo: String::from("Hello"),
1599
bar: 123,
1600
}
1601
}
1602
}
1603
1604
let expected = MyStruct {
1605
foo: String::from("Hello"),
1606
bar: 123,
1607
};
1608
1609
let dyn_struct = DynamicStruct::default();
1610
let my_struct = <MyStruct as FromReflect>::from_reflect(&dyn_struct);
1611
1612
assert_eq!(Some(expected), my_struct);
1613
}
1614
1615
#[test]
1616
fn reflect_complex_patch() {
1617
#[derive(Reflect, Eq, PartialEq, Debug)]
1618
#[reflect(PartialEq)]
1619
struct Foo {
1620
a: u32,
1621
#[reflect(ignore)]
1622
_b: u32,
1623
c: Vec<isize>,
1624
d: HashMap<usize, i8>,
1625
e: Bar,
1626
f: (i32, Vec<isize>, Bar),
1627
g: Vec<(Baz, HashMap<usize, Bar>)>,
1628
h: [u32; 2],
1629
}
1630
1631
#[derive(Reflect, Eq, PartialEq, Clone, Debug)]
1632
#[reflect(PartialEq)]
1633
struct Bar {
1634
x: u32,
1635
}
1636
1637
#[derive(Reflect, Eq, PartialEq, Debug)]
1638
struct Baz(String);
1639
1640
let mut hash_map = <HashMap<_, _>>::default();
1641
hash_map.insert(1, 1);
1642
hash_map.insert(2, 2);
1643
1644
let mut hash_map_baz = <HashMap<_, _>>::default();
1645
hash_map_baz.insert(1, Bar { x: 0 });
1646
1647
let mut foo = Foo {
1648
a: 1,
1649
_b: 1,
1650
c: vec![1, 2],
1651
d: hash_map,
1652
e: Bar { x: 1 },
1653
f: (1, vec![1, 2], Bar { x: 1 }),
1654
g: vec![(Baz("string".to_string()), hash_map_baz)],
1655
h: [2; 2],
1656
};
1657
1658
let mut foo_patch = DynamicStruct::default();
1659
foo_patch.insert("a", 2u32);
1660
foo_patch.insert("b", 2u32); // this should be ignored
1661
1662
let mut list = DynamicList::default();
1663
list.push(3isize);
1664
list.push(4isize);
1665
list.push(5isize);
1666
foo_patch.insert("c", list.to_dynamic_list());
1667
1668
let mut map = DynamicMap::default();
1669
map.insert(2usize, 3i8);
1670
map.insert(3usize, 4i8);
1671
foo_patch.insert("d", map);
1672
1673
let mut bar_patch = DynamicStruct::default();
1674
bar_patch.insert("x", 2u32);
1675
foo_patch.insert("e", bar_patch.to_dynamic_struct());
1676
1677
let mut tuple = DynamicTuple::default();
1678
tuple.insert(2i32);
1679
tuple.insert(list);
1680
tuple.insert(bar_patch);
1681
foo_patch.insert("f", tuple);
1682
1683
let mut composite = DynamicList::default();
1684
composite.push({
1685
let mut tuple = DynamicTuple::default();
1686
tuple.insert({
1687
let mut tuple_struct = DynamicTupleStruct::default();
1688
tuple_struct.insert("new_string".to_string());
1689
tuple_struct
1690
});
1691
tuple.insert({
1692
let mut map = DynamicMap::default();
1693
map.insert(1usize, {
1694
let mut struct_ = DynamicStruct::default();
1695
struct_.insert("x", 7u32);
1696
struct_
1697
});
1698
map
1699
});
1700
tuple
1701
});
1702
foo_patch.insert("g", composite);
1703
1704
let array = DynamicArray::from_iter([2u32, 2u32]);
1705
foo_patch.insert("h", array);
1706
1707
foo.apply(&foo_patch);
1708
1709
let mut hash_map = <HashMap<_, _>>::default();
1710
hash_map.insert(2, 3);
1711
hash_map.insert(3, 4);
1712
1713
let mut hash_map_baz = <HashMap<_, _>>::default();
1714
hash_map_baz.insert(1, Bar { x: 7 });
1715
1716
let expected_foo = Foo {
1717
a: 2,
1718
_b: 1,
1719
c: vec![3, 4, 5],
1720
d: hash_map,
1721
e: Bar { x: 2 },
1722
f: (2, vec![3, 4, 5], Bar { x: 2 }),
1723
g: vec![(Baz("new_string".to_string()), hash_map_baz.clone())],
1724
h: [2; 2],
1725
};
1726
1727
assert_eq!(foo, expected_foo);
1728
1729
let new_foo = Foo::from_reflect(&foo_patch)
1730
.expect("error while creating a concrete type from a dynamic type");
1731
1732
let mut hash_map = <HashMap<_, _>>::default();
1733
hash_map.insert(2, 3);
1734
hash_map.insert(3, 4);
1735
1736
let expected_new_foo = Foo {
1737
a: 2,
1738
_b: 0,
1739
c: vec![3, 4, 5],
1740
d: hash_map,
1741
e: Bar { x: 2 },
1742
f: (2, vec![3, 4, 5], Bar { x: 2 }),
1743
g: vec![(Baz("new_string".to_string()), hash_map_baz)],
1744
h: [2; 2],
1745
};
1746
1747
assert_eq!(new_foo, expected_new_foo);
1748
}
1749
1750
#[test]
1751
fn should_auto_register_fields() {
1752
#[derive(Reflect)]
1753
struct Foo {
1754
bar: Bar,
1755
}
1756
1757
#[derive(Reflect)]
1758
enum Bar {
1759
Variant(Baz),
1760
}
1761
1762
#[derive(Reflect)]
1763
struct Baz(usize);
1764
1765
// === Basic === //
1766
let mut registry = TypeRegistry::empty();
1767
registry.register::<Foo>();
1768
1769
assert!(
1770
registry.contains(TypeId::of::<Bar>()),
1771
"registry should contain auto-registered `Bar` from `Foo`"
1772
);
1773
1774
// === Option === //
1775
let mut registry = TypeRegistry::empty();
1776
registry.register::<Option<Foo>>();
1777
1778
assert!(
1779
registry.contains(TypeId::of::<Bar>()),
1780
"registry should contain auto-registered `Bar` from `Option<Foo>`"
1781
);
1782
1783
// === Tuple === //
1784
let mut registry = TypeRegistry::empty();
1785
registry.register::<(Foo, Foo)>();
1786
1787
assert!(
1788
registry.contains(TypeId::of::<Bar>()),
1789
"registry should contain auto-registered `Bar` from `(Foo, Foo)`"
1790
);
1791
1792
// === Array === //
1793
let mut registry = TypeRegistry::empty();
1794
registry.register::<[Foo; 3]>();
1795
1796
assert!(
1797
registry.contains(TypeId::of::<Bar>()),
1798
"registry should contain auto-registered `Bar` from `[Foo; 3]`"
1799
);
1800
1801
// === Vec === //
1802
let mut registry = TypeRegistry::empty();
1803
registry.register::<Vec<Foo>>();
1804
1805
assert!(
1806
registry.contains(TypeId::of::<Bar>()),
1807
"registry should contain auto-registered `Bar` from `Vec<Foo>`"
1808
);
1809
1810
// === HashMap === //
1811
let mut registry = TypeRegistry::empty();
1812
registry.register::<HashMap<i32, Foo>>();
1813
1814
assert!(
1815
registry.contains(TypeId::of::<Bar>()),
1816
"registry should contain auto-registered `Bar` from `HashMap<i32, Foo>`"
1817
);
1818
}
1819
1820
#[test]
1821
fn should_allow_dynamic_fields() {
1822
#[derive(Reflect)]
1823
#[reflect(from_reflect = false)]
1824
struct MyStruct(
1825
DynamicEnum,
1826
DynamicTupleStruct,
1827
DynamicStruct,
1828
DynamicMap,
1829
DynamicList,
1830
DynamicArray,
1831
DynamicTuple,
1832
i32,
1833
);
1834
1835
assert_impl_all!(MyStruct: Reflect, GetTypeRegistration);
1836
1837
let mut registry = TypeRegistry::empty();
1838
registry.register::<MyStruct>();
1839
1840
assert_eq!(2, registry.iter().count());
1841
assert!(registry.contains(TypeId::of::<MyStruct>()));
1842
assert!(registry.contains(TypeId::of::<i32>()));
1843
}
1844
1845
#[test]
1846
fn should_not_auto_register_existing_types() {
1847
#[derive(Reflect)]
1848
struct Foo {
1849
bar: Bar,
1850
}
1851
1852
#[derive(Reflect, Default)]
1853
struct Bar(usize);
1854
1855
let mut registry = TypeRegistry::empty();
1856
registry.register::<Bar>();
1857
registry.register_type_data::<Bar, ReflectDefault>();
1858
registry.register::<Foo>();
1859
1860
assert!(
1861
registry
1862
.get_type_data::<ReflectDefault>(TypeId::of::<Bar>())
1863
.is_some(),
1864
"registry should contain existing registration for `Bar`"
1865
);
1866
}
1867
1868
#[test]
1869
fn reflect_serialize() {
1870
#[derive(Reflect)]
1871
struct Foo {
1872
a: u32,
1873
#[reflect(ignore)]
1874
_b: u32,
1875
c: Vec<isize>,
1876
d: HashMap<usize, i8>,
1877
e: Bar,
1878
f: String,
1879
g: (i32, Vec<isize>, Bar),
1880
h: [u32; 2],
1881
}
1882
1883
#[derive(Reflect, Serialize, Deserialize)]
1884
#[reflect(Serialize, Deserialize)]
1885
struct Bar {
1886
x: u32,
1887
}
1888
1889
let mut hash_map = <HashMap<_, _>>::default();
1890
hash_map.insert(1, 1);
1891
hash_map.insert(2, 2);
1892
let foo = Foo {
1893
a: 1,
1894
_b: 1,
1895
c: vec![1, 2],
1896
d: hash_map,
1897
e: Bar { x: 1 },
1898
f: "hi".to_string(),
1899
g: (1, vec![1, 2], Bar { x: 1 }),
1900
h: [2; 2],
1901
};
1902
1903
let mut registry = TypeRegistry::default();
1904
registry.register::<u32>();
1905
registry.register::<i8>();
1906
registry.register::<i32>();
1907
registry.register::<usize>();
1908
registry.register::<isize>();
1909
registry.register::<Foo>();
1910
registry.register::<Bar>();
1911
registry.register::<String>();
1912
registry.register::<Vec<isize>>();
1913
registry.register::<HashMap<usize, i8>>();
1914
registry.register::<(i32, Vec<isize>, Bar)>();
1915
registry.register::<[u32; 2]>();
1916
1917
let serializer = ReflectSerializer::new(&foo, &registry);
1918
let serialized = to_string_pretty(&serializer, PrettyConfig::default()).unwrap();
1919
1920
let mut deserializer = Deserializer::from_str(&serialized).unwrap();
1921
let reflect_deserializer = ReflectDeserializer::new(&registry);
1922
let value = reflect_deserializer.deserialize(&mut deserializer).unwrap();
1923
let roundtrip_foo = Foo::from_reflect(value.as_partial_reflect()).unwrap();
1924
1925
assert!(foo.reflect_partial_eq(&roundtrip_foo).unwrap());
1926
}
1927
1928
#[test]
1929
fn reflect_downcast() {
1930
#[derive(Reflect, Clone, Debug, PartialEq)]
1931
struct Bar {
1932
y: u8,
1933
}
1934
1935
#[derive(Reflect, Clone, Debug, PartialEq)]
1936
struct Foo {
1937
x: i32,
1938
s: String,
1939
b: Bar,
1940
u: usize,
1941
t: ([f32; 3], String),
1942
v: Cow<'static, str>,
1943
w: Cow<'static, [u8]>,
1944
}
1945
1946
let foo = Foo {
1947
x: 123,
1948
s: "String".to_string(),
1949
b: Bar { y: 255 },
1950
u: 1111111111111,
1951
t: ([3.0, 2.0, 1.0], "Tuple String".to_string()),
1952
v: Cow::Owned("Cow String".to_string()),
1953
w: Cow::Owned(vec![1, 2, 3]),
1954
};
1955
1956
let foo2: Box<dyn Reflect> = Box::new(foo.clone());
1957
1958
assert_eq!(foo, *foo2.downcast::<Foo>().unwrap());
1959
}
1960
1961
#[test]
1962
fn should_drain_fields() {
1963
let array_value: Box<dyn Array> = Box::new([123_i32, 321_i32]);
1964
let fields = array_value.drain();
1965
assert!(fields[0].reflect_partial_eq(&123_i32).unwrap_or_default());
1966
assert!(fields[1].reflect_partial_eq(&321_i32).unwrap_or_default());
1967
1968
let mut list_value: Box<dyn List> = Box::new(vec![123_i32, 321_i32]);
1969
let fields = list_value.drain();
1970
assert!(fields[0].reflect_partial_eq(&123_i32).unwrap_or_default());
1971
assert!(fields[1].reflect_partial_eq(&321_i32).unwrap_or_default());
1972
1973
let tuple_value: Box<dyn Tuple> = Box::new((123_i32, 321_i32));
1974
let fields = tuple_value.drain();
1975
assert!(fields[0].reflect_partial_eq(&123_i32).unwrap_or_default());
1976
assert!(fields[1].reflect_partial_eq(&321_i32).unwrap_or_default());
1977
1978
let mut map_value: Box<dyn Map> =
1979
Box::new([(123_i32, 321_i32)].into_iter().collect::<HashMap<_, _>>());
1980
let fields = map_value.drain();
1981
assert!(fields[0].0.reflect_partial_eq(&123_i32).unwrap_or_default());
1982
assert!(fields[0].1.reflect_partial_eq(&321_i32).unwrap_or_default());
1983
}
1984
1985
#[test]
1986
fn reflect_take() {
1987
#[derive(Reflect, Debug, PartialEq)]
1988
#[reflect(PartialEq)]
1989
struct Bar {
1990
x: u32,
1991
}
1992
1993
let x: Box<dyn Reflect> = Box::new(Bar { x: 2 });
1994
let y = x.take::<Bar>().unwrap();
1995
assert_eq!(y, Bar { x: 2 });
1996
}
1997
1998
#[test]
1999
fn not_dynamic_names() {
2000
let list = Vec::<usize>::new();
2001
let dyn_list = list.to_dynamic_list();
2002
assert_ne!(dyn_list.reflect_type_path(), Vec::<usize>::type_path());
2003
2004
let array = [b'0'; 4];
2005
let dyn_array = array.to_dynamic_array();
2006
assert_ne!(dyn_array.reflect_type_path(), <[u8; 4]>::type_path());
2007
2008
let map = HashMap::<usize, String>::default();
2009
let dyn_map = map.to_dynamic_map();
2010
assert_ne!(
2011
dyn_map.reflect_type_path(),
2012
HashMap::<usize, String>::type_path()
2013
);
2014
2015
let tuple = (0usize, "1".to_string(), 2.0f32);
2016
let mut dyn_tuple = tuple.to_dynamic_tuple();
2017
dyn_tuple.insert::<usize>(3);
2018
assert_ne!(
2019
dyn_tuple.reflect_type_path(),
2020
<(usize, String, f32, usize)>::type_path()
2021
);
2022
2023
#[derive(Reflect)]
2024
struct TestStruct {
2025
a: usize,
2026
}
2027
let struct_ = TestStruct { a: 0 };
2028
let dyn_struct = struct_.to_dynamic_struct();
2029
assert_ne!(dyn_struct.reflect_type_path(), TestStruct::type_path());
2030
2031
#[derive(Reflect)]
2032
struct TestTupleStruct(usize);
2033
let tuple_struct = TestTupleStruct(0);
2034
let dyn_tuple_struct = tuple_struct.to_dynamic_tuple_struct();
2035
assert_ne!(
2036
dyn_tuple_struct.reflect_type_path(),
2037
TestTupleStruct::type_path()
2038
);
2039
}
2040
2041
macro_rules! assert_type_paths {
2042
($($ty:ty => $long:literal, $short:literal,)*) => {
2043
$(
2044
assert_eq!(<$ty as TypePath>::type_path(), $long);
2045
assert_eq!(<$ty as TypePath>::short_type_path(), $short);
2046
)*
2047
};
2048
}
2049
2050
#[test]
2051
fn reflect_type_path() {
2052
#[derive(TypePath)]
2053
struct Param;
2054
2055
#[derive(TypePath)]
2056
struct Derive;
2057
2058
#[derive(TypePath)]
2059
#[type_path = "my_alias"]
2060
struct DerivePath;
2061
2062
#[derive(TypePath)]
2063
#[type_path = "my_alias"]
2064
#[type_name = "MyDerivePathName"]
2065
struct DerivePathName;
2066
2067
#[derive(TypePath)]
2068
struct DeriveG<T>(PhantomData<T>);
2069
2070
#[derive(TypePath)]
2071
#[type_path = "my_alias"]
2072
struct DerivePathG<T, const N: usize>(PhantomData<T>);
2073
2074
#[derive(TypePath)]
2075
#[type_path = "my_alias"]
2076
#[type_name = "MyDerivePathNameG"]
2077
struct DerivePathNameG<T>(PhantomData<T>);
2078
2079
struct Macro;
2080
impl_type_path!((in my_alias) Macro);
2081
2082
struct MacroName;
2083
impl_type_path!((in my_alias as MyMacroName) MacroName);
2084
2085
struct MacroG<T, const N: usize>(PhantomData<T>);
2086
impl_type_path!((in my_alias) MacroG<T, const N: usize>);
2087
2088
struct MacroNameG<T>(PhantomData<T>);
2089
impl_type_path!((in my_alias as MyMacroNameG) MacroNameG<T>);
2090
2091
assert_type_paths! {
2092
Derive => "bevy_reflect::tests::Derive", "Derive",
2093
DerivePath => "my_alias::DerivePath", "DerivePath",
2094
DerivePathName => "my_alias::MyDerivePathName", "MyDerivePathName",
2095
DeriveG<Param> => "bevy_reflect::tests::DeriveG<bevy_reflect::tests::Param>", "DeriveG<Param>",
2096
DerivePathG<Param, 10> => "my_alias::DerivePathG<bevy_reflect::tests::Param, 10>", "DerivePathG<Param, 10>",
2097
DerivePathNameG<Param> => "my_alias::MyDerivePathNameG<bevy_reflect::tests::Param>", "MyDerivePathNameG<Param>",
2098
Macro => "my_alias::Macro", "Macro",
2099
MacroName => "my_alias::MyMacroName", "MyMacroName",
2100
MacroG<Param, 10> => "my_alias::MacroG<bevy_reflect::tests::Param, 10>", "MacroG<Param, 10>",
2101
MacroNameG<Param> => "my_alias::MyMacroNameG<bevy_reflect::tests::Param>", "MyMacroNameG<Param>",
2102
}
2103
}
2104
2105
#[test]
2106
fn std_type_paths() {
2107
#[derive(Clone)]
2108
struct Type;
2109
2110
impl TypePath for Type {
2111
fn type_path() -> &'static str {
2112
// for brevity in tests
2113
"Long"
2114
}
2115
2116
fn short_type_path() -> &'static str {
2117
"Short"
2118
}
2119
}
2120
2121
assert_type_paths! {
2122
u8 => "u8", "u8",
2123
Type => "Long", "Short",
2124
&Type => "&Long", "&Short",
2125
[Type] => "[Long]", "[Short]",
2126
&[Type] => "&[Long]", "&[Short]",
2127
[Type; 0] => "[Long; 0]", "[Short; 0]",
2128
[Type; 100] => "[Long; 100]", "[Short; 100]",
2129
() => "()", "()",
2130
(Type,) => "(Long,)", "(Short,)",
2131
(Type, Type) => "(Long, Long)", "(Short, Short)",
2132
(Type, Type, Type) => "(Long, Long, Long)", "(Short, Short, Short)",
2133
Cow<'static, Type> => "alloc::borrow::Cow<Long>", "Cow<Short>",
2134
}
2135
}
2136
2137
#[test]
2138
fn reflect_type_info() {
2139
// TypeInfo
2140
let info = i32::type_info();
2141
assert_eq!(i32::type_path(), info.type_path());
2142
assert_eq!(TypeId::of::<i32>(), info.type_id());
2143
2144
// TypeInfo (unsized)
2145
assert_eq!(
2146
TypeId::of::<dyn Reflect>(),
2147
<dyn Reflect as Typed>::type_info().type_id()
2148
);
2149
2150
// TypeInfo (instance)
2151
let value: &dyn Reflect = &123_i32;
2152
let info = value.reflect_type_info();
2153
assert!(info.is::<i32>());
2154
2155
// Struct
2156
#[derive(Reflect)]
2157
struct MyStruct {
2158
foo: i32,
2159
bar: usize,
2160
}
2161
2162
let info = MyStruct::type_info().as_struct().unwrap();
2163
assert!(info.is::<MyStruct>());
2164
assert_eq!(MyStruct::type_path(), info.type_path());
2165
assert_eq!(i32::type_path(), info.field("foo").unwrap().type_path());
2166
assert_eq!(TypeId::of::<i32>(), info.field("foo").unwrap().type_id());
2167
assert!(info.field("foo").unwrap().type_info().unwrap().is::<i32>());
2168
assert!(info.field("foo").unwrap().is::<i32>());
2169
assert_eq!("foo", info.field("foo").unwrap().name());
2170
assert_eq!(usize::type_path(), info.field_at(1).unwrap().type_path());
2171
2172
let value: &dyn Reflect = &MyStruct { foo: 123, bar: 321 };
2173
let info = value.reflect_type_info();
2174
assert!(info.is::<MyStruct>());
2175
2176
// Struct (generic)
2177
#[derive(Reflect)]
2178
struct MyGenericStruct<T> {
2179
foo: T,
2180
bar: usize,
2181
}
2182
2183
let info = <MyGenericStruct<i32>>::type_info().as_struct().unwrap();
2184
assert!(info.is::<MyGenericStruct<i32>>());
2185
assert_eq!(MyGenericStruct::<i32>::type_path(), info.type_path());
2186
assert_eq!(i32::type_path(), info.field("foo").unwrap().type_path());
2187
assert_eq!("foo", info.field("foo").unwrap().name());
2188
assert!(info.field("foo").unwrap().type_info().unwrap().is::<i32>());
2189
assert_eq!(usize::type_path(), info.field_at(1).unwrap().type_path());
2190
2191
let value: &dyn Reflect = &MyGenericStruct {
2192
foo: String::from("Hello!"),
2193
bar: 321,
2194
};
2195
let info = value.reflect_type_info();
2196
assert!(info.is::<MyGenericStruct<String>>());
2197
2198
// Struct (dynamic field)
2199
#[derive(Reflect)]
2200
#[reflect(from_reflect = false)]
2201
struct MyDynamicStruct {
2202
foo: DynamicStruct,
2203
bar: usize,
2204
}
2205
2206
let info = MyDynamicStruct::type_info();
2207
if let TypeInfo::Struct(info) = info {
2208
assert!(info.is::<MyDynamicStruct>());
2209
assert_eq!(MyDynamicStruct::type_path(), info.type_path());
2210
assert_eq!(
2211
DynamicStruct::type_path(),
2212
info.field("foo").unwrap().type_path()
2213
);
2214
assert_eq!("foo", info.field("foo").unwrap().name());
2215
assert!(info.field("foo").unwrap().type_info().is_none());
2216
assert_eq!(usize::type_path(), info.field_at(1).unwrap().type_path());
2217
} else {
2218
panic!("Expected `TypeInfo::Struct`");
2219
}
2220
2221
let value: &dyn Reflect = &MyDynamicStruct {
2222
foo: DynamicStruct::default(),
2223
bar: 321,
2224
};
2225
let info = value.reflect_type_info();
2226
assert!(info.is::<MyDynamicStruct>());
2227
2228
// Tuple Struct
2229
#[derive(Reflect)]
2230
struct MyTupleStruct(usize, i32, MyStruct);
2231
2232
let info = MyTupleStruct::type_info().as_tuple_struct().unwrap();
2233
2234
assert!(info.is::<MyTupleStruct>());
2235
assert_eq!(MyTupleStruct::type_path(), info.type_path());
2236
assert_eq!(i32::type_path(), info.field_at(1).unwrap().type_path());
2237
assert!(info.field_at(1).unwrap().type_info().unwrap().is::<i32>());
2238
assert!(info.field_at(1).unwrap().is::<i32>());
2239
2240
// Tuple
2241
type MyTuple = (u32, f32, String);
2242
2243
let info = MyTuple::type_info().as_tuple().unwrap();
2244
2245
assert!(info.is::<MyTuple>());
2246
assert_eq!(MyTuple::type_path(), info.type_path());
2247
assert_eq!(f32::type_path(), info.field_at(1).unwrap().type_path());
2248
assert!(info.field_at(1).unwrap().type_info().unwrap().is::<f32>());
2249
2250
let value: &dyn Reflect = &(123_u32, 1.23_f32, String::from("Hello!"));
2251
let info = value.reflect_type_info();
2252
assert!(info.is::<MyTuple>());
2253
2254
// List
2255
type MyList = Vec<usize>;
2256
2257
let info = MyList::type_info().as_list().unwrap();
2258
2259
assert!(info.is::<MyList>());
2260
assert!(info.item_ty().is::<usize>());
2261
assert!(info.item_info().unwrap().is::<usize>());
2262
assert_eq!(MyList::type_path(), info.type_path());
2263
assert_eq!(usize::type_path(), info.item_ty().path());
2264
2265
let value: &dyn Reflect = &vec![123_usize];
2266
let info = value.reflect_type_info();
2267
assert!(info.is::<MyList>());
2268
2269
// List (SmallVec)
2270
#[cfg(feature = "smallvec")]
2271
{
2272
type MySmallVec = smallvec::SmallVec<[String; 2]>;
2273
2274
let info = MySmallVec::type_info().as_list().unwrap();
2275
assert!(info.is::<MySmallVec>());
2276
assert!(info.item_ty().is::<String>());
2277
assert!(info.item_info().unwrap().is::<String>());
2278
assert_eq!(MySmallVec::type_path(), info.type_path());
2279
assert_eq!(String::type_path(), info.item_ty().path());
2280
2281
let value: MySmallVec = smallvec::smallvec![String::default(); 2];
2282
let value: &dyn Reflect = &value;
2283
let info = value.reflect_type_info();
2284
assert!(info.is::<MySmallVec>());
2285
}
2286
2287
// Array
2288
type MyArray = [usize; 3];
2289
2290
let info = MyArray::type_info().as_array().unwrap();
2291
assert!(info.is::<MyArray>());
2292
assert!(info.item_ty().is::<usize>());
2293
assert!(info.item_info().unwrap().is::<usize>());
2294
assert_eq!(MyArray::type_path(), info.type_path());
2295
assert_eq!(usize::type_path(), info.item_ty().path());
2296
assert_eq!(3, info.capacity());
2297
2298
let value: &dyn Reflect = &[1usize, 2usize, 3usize];
2299
let info = value.reflect_type_info();
2300
assert!(info.is::<MyArray>());
2301
2302
// Cow<'static, str>
2303
type MyCowStr = Cow<'static, str>;
2304
2305
let info = MyCowStr::type_info().as_opaque().unwrap();
2306
2307
assert!(info.is::<MyCowStr>());
2308
assert_eq!(core::any::type_name::<MyCowStr>(), info.type_path());
2309
2310
let value: &dyn Reflect = &Cow::<'static, str>::Owned("Hello!".to_string());
2311
let info = value.reflect_type_info();
2312
assert!(info.is::<MyCowStr>());
2313
2314
// Cow<'static, [u8]>
2315
type MyCowSlice = Cow<'static, [u8]>;
2316
2317
let info = MyCowSlice::type_info().as_list().unwrap();
2318
2319
assert!(info.is::<MyCowSlice>());
2320
assert!(info.item_ty().is::<u8>());
2321
assert!(info.item_info().unwrap().is::<u8>());
2322
assert_eq!(core::any::type_name::<MyCowSlice>(), info.type_path());
2323
assert_eq!(core::any::type_name::<u8>(), info.item_ty().path());
2324
2325
let value: &dyn Reflect = &Cow::<'static, [u8]>::Owned(vec![0, 1, 2, 3]);
2326
let info = value.reflect_type_info();
2327
assert!(info.is::<MyCowSlice>());
2328
2329
// Map
2330
type MyMap = HashMap<usize, f32>;
2331
2332
let info = MyMap::type_info().as_map().unwrap();
2333
2334
assert!(info.is::<MyMap>());
2335
assert!(info.key_ty().is::<usize>());
2336
assert!(info.value_ty().is::<f32>());
2337
assert!(info.key_info().unwrap().is::<usize>());
2338
assert!(info.value_info().unwrap().is::<f32>());
2339
assert_eq!(MyMap::type_path(), info.type_path());
2340
assert_eq!(usize::type_path(), info.key_ty().path());
2341
assert_eq!(f32::type_path(), info.value_ty().path());
2342
2343
let value: &dyn Reflect = &MyMap::default();
2344
let info = value.reflect_type_info();
2345
assert!(info.is::<MyMap>());
2346
2347
// Value
2348
type MyValue = String;
2349
2350
let info = MyValue::type_info().as_opaque().unwrap();
2351
2352
assert!(info.is::<MyValue>());
2353
assert_eq!(MyValue::type_path(), info.type_path());
2354
2355
let value: &dyn Reflect = &String::from("Hello!");
2356
let info = value.reflect_type_info();
2357
assert!(info.is::<MyValue>());
2358
}
2359
2360
#[test]
2361
fn get_represented_kind_info() {
2362
#[derive(Reflect)]
2363
struct SomeStruct;
2364
2365
#[derive(Reflect)]
2366
struct SomeTupleStruct(f32);
2367
2368
#[derive(Reflect)]
2369
enum SomeEnum {
2370
Foo,
2371
Bar,
2372
}
2373
2374
let dyn_struct: &dyn Struct = &SomeStruct;
2375
let _: &StructInfo = dyn_struct.get_represented_struct_info().unwrap();
2376
2377
let dyn_map: &dyn Map = &HashMap::<(), ()>::default();
2378
let _: &MapInfo = dyn_map.get_represented_map_info().unwrap();
2379
2380
let dyn_array: &dyn Array = &[1, 2, 3];
2381
let _: &ArrayInfo = dyn_array.get_represented_array_info().unwrap();
2382
2383
let dyn_list: &dyn List = &vec![1, 2, 3];
2384
let _: &ListInfo = dyn_list.get_represented_list_info().unwrap();
2385
2386
let dyn_tuple_struct: &dyn TupleStruct = &SomeTupleStruct(5.0);
2387
let _: &TupleStructInfo = dyn_tuple_struct
2388
.get_represented_tuple_struct_info()
2389
.unwrap();
2390
2391
let dyn_enum: &dyn Enum = &SomeEnum::Foo;
2392
let _: &EnumInfo = dyn_enum.get_represented_enum_info().unwrap();
2393
}
2394
2395
#[test]
2396
fn should_permit_higher_ranked_lifetimes() {
2397
#[derive(Reflect)]
2398
#[reflect(from_reflect = false)]
2399
struct TestStruct {
2400
#[reflect(ignore)]
2401
_hrl: for<'a> fn(&'a str) -> &'a str,
2402
}
2403
2404
impl Default for TestStruct {
2405
fn default() -> Self {
2406
TestStruct {
2407
_hrl: |input| input,
2408
}
2409
}
2410
}
2411
2412
fn get_type_registration<T: GetTypeRegistration>() {}
2413
get_type_registration::<TestStruct>();
2414
}
2415
2416
#[test]
2417
fn should_permit_valid_represented_type_for_dynamic() {
2418
let type_info = <[i32; 2] as Typed>::type_info();
2419
let mut dynamic_array = [123; 2].to_dynamic_array();
2420
dynamic_array.set_represented_type(Some(type_info));
2421
}
2422
2423
#[test]
2424
#[should_panic(expected = "expected TypeInfo::Array but received")]
2425
fn should_prohibit_invalid_represented_type_for_dynamic() {
2426
let type_info = <(i32, i32) as Typed>::type_info();
2427
let mut dynamic_array = [123; 2].to_dynamic_array();
2428
dynamic_array.set_represented_type(Some(type_info));
2429
}
2430
2431
#[cfg(feature = "documentation")]
2432
mod docstrings {
2433
use super::*;
2434
2435
#[test]
2436
fn should_not_contain_docs() {
2437
// Regular comments do not count as doc comments,
2438
// and are therefore not reflected.
2439
#[derive(Reflect)]
2440
struct SomeStruct;
2441
2442
let info = <SomeStruct as Typed>::type_info();
2443
assert_eq!(None, info.docs());
2444
2445
// Block comments do not count as doc comments,
2446
// and are therefore not reflected.
2447
#[derive(Reflect)]
2448
struct SomeOtherStruct;
2449
2450
let info = <SomeOtherStruct as Typed>::type_info();
2451
assert_eq!(None, info.docs());
2452
}
2453
2454
#[test]
2455
fn should_contain_docs() {
2456
/// Some struct.
2457
///
2458
/// # Example
2459
///
2460
/// ```ignore (This is only used for a unit test, no need to doc test)
2461
/// let some_struct = SomeStruct;
2462
/// ```
2463
#[derive(Reflect)]
2464
struct SomeStruct;
2465
2466
let info = <SomeStruct as Typed>::type_info();
2467
assert_eq!(
2468
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 ```"),
2469
info.docs()
2470
);
2471
2472
#[doc = "The compiler automatically converts `///`-style comments into `#[doc]` attributes."]
2473
#[doc = "Of course, you _could_ use the attribute directly if you wanted to."]
2474
#[doc = "Both will be reflected."]
2475
#[derive(Reflect)]
2476
struct SomeOtherStruct;
2477
2478
let info = <SomeOtherStruct as Typed>::type_info();
2479
assert_eq!(
2480
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."),
2481
info.docs()
2482
);
2483
2484
/// Some tuple struct.
2485
#[derive(Reflect)]
2486
struct SomeTupleStruct(usize);
2487
2488
let info = <SomeTupleStruct as Typed>::type_info();
2489
assert_eq!(Some(" Some tuple struct."), info.docs());
2490
2491
/// Some enum.
2492
#[derive(Reflect)]
2493
enum SomeEnum {
2494
Foo,
2495
}
2496
2497
let info = <SomeEnum as Typed>::type_info();
2498
assert_eq!(Some(" Some enum."), info.docs());
2499
2500
#[derive(Clone)]
2501
struct SomePrimitive;
2502
impl_reflect_opaque!(
2503
/// Some primitive for which we have attributed custom documentation.
2504
(in bevy_reflect::tests) SomePrimitive
2505
);
2506
2507
let info = <SomePrimitive as Typed>::type_info();
2508
assert_eq!(
2509
Some(" Some primitive for which we have attributed custom documentation."),
2510
info.docs()
2511
);
2512
}
2513
2514
#[test]
2515
fn fields_should_contain_docs() {
2516
#[derive(Reflect)]
2517
struct SomeStruct {
2518
/// The name
2519
name: String,
2520
/// The index
2521
index: usize,
2522
// Not documented...
2523
data: Vec<i32>,
2524
}
2525
2526
let info = <SomeStruct as Typed>::type_info().as_struct().unwrap();
2527
2528
let mut fields = info.iter();
2529
assert_eq!(Some(" The name"), fields.next().unwrap().docs());
2530
assert_eq!(Some(" The index"), fields.next().unwrap().docs());
2531
assert_eq!(None, fields.next().unwrap().docs());
2532
}
2533
2534
#[test]
2535
fn variants_should_contain_docs() {
2536
#[derive(Reflect)]
2537
enum SomeEnum {
2538
// Not documented...
2539
Nothing,
2540
/// Option A
2541
A(
2542
/// Index
2543
usize,
2544
),
2545
/// Option B
2546
B {
2547
/// Name
2548
name: String,
2549
},
2550
}
2551
2552
let info = <SomeEnum as Typed>::type_info().as_enum().unwrap();
2553
2554
let mut variants = info.iter();
2555
assert_eq!(None, variants.next().unwrap().docs());
2556
2557
let variant = variants.next().unwrap().as_tuple_variant().unwrap();
2558
assert_eq!(Some(" Option A"), variant.docs());
2559
let field = variant.field_at(0).unwrap();
2560
assert_eq!(Some(" Index"), field.docs());
2561
2562
let variant = variants.next().unwrap().as_struct_variant().unwrap();
2563
assert_eq!(Some(" Option B"), variant.docs());
2564
let field = variant.field_at(0).unwrap();
2565
assert_eq!(Some(" Name"), field.docs());
2566
}
2567
}
2568
2569
#[test]
2570
fn into_reflect() {
2571
trait TestTrait: Reflect {}
2572
2573
#[derive(Reflect)]
2574
struct TestStruct;
2575
2576
impl TestTrait for TestStruct {}
2577
2578
let trait_object: Box<dyn TestTrait> = Box::new(TestStruct);
2579
2580
// Should compile:
2581
let _ = trait_object.into_reflect();
2582
}
2583
2584
#[test]
2585
fn as_reflect() {
2586
trait TestTrait: Reflect {}
2587
2588
#[derive(Reflect)]
2589
struct TestStruct;
2590
2591
impl TestTrait for TestStruct {}
2592
2593
let trait_object: Box<dyn TestTrait> = Box::new(TestStruct);
2594
2595
// Should compile:
2596
let _ = trait_object.as_reflect();
2597
}
2598
2599
#[test]
2600
fn should_reflect_debug() {
2601
#[derive(Reflect)]
2602
struct Test {
2603
value: usize,
2604
list: Vec<String>,
2605
array: [f32; 3],
2606
map: HashMap<i32, f32>,
2607
a_struct: SomeStruct,
2608
a_tuple_struct: SomeTupleStruct,
2609
enum_unit: SomeEnum,
2610
enum_tuple: SomeEnum,
2611
enum_struct: SomeEnum,
2612
custom: CustomDebug,
2613
#[reflect(ignore)]
2614
#[expect(dead_code, reason = "This value is intended to not be reflected.")]
2615
ignored: isize,
2616
}
2617
2618
#[derive(Reflect)]
2619
struct SomeStruct {
2620
foo: String,
2621
}
2622
2623
#[derive(Reflect)]
2624
enum SomeEnum {
2625
A,
2626
B(usize),
2627
C { value: i32 },
2628
}
2629
2630
#[derive(Reflect)]
2631
struct SomeTupleStruct(String);
2632
2633
#[derive(Reflect)]
2634
#[reflect(Debug)]
2635
struct CustomDebug;
2636
impl Debug for CustomDebug {
2637
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
2638
f.write_str("Cool debug!")
2639
}
2640
}
2641
2642
let mut map = <HashMap<_, _>>::default();
2643
map.insert(123, 1.23);
2644
2645
let test = Test {
2646
value: 123,
2647
list: vec![String::from("A"), String::from("B"), String::from("C")],
2648
array: [1.0, 2.0, 3.0],
2649
map,
2650
a_struct: SomeStruct {
2651
foo: String::from("A Struct!"),
2652
},
2653
a_tuple_struct: SomeTupleStruct(String::from("A Tuple Struct!")),
2654
enum_unit: SomeEnum::A,
2655
enum_tuple: SomeEnum::B(123),
2656
enum_struct: SomeEnum::C { value: 321 },
2657
custom: CustomDebug,
2658
ignored: 321,
2659
};
2660
2661
let reflected: &dyn Reflect = &test;
2662
let expected = r#"
2663
bevy_reflect::tests::Test {
2664
value: 123,
2665
list: [
2666
"A",
2667
"B",
2668
"C",
2669
],
2670
array: [
2671
1.0,
2672
2.0,
2673
3.0,
2674
],
2675
map: {
2676
123: 1.23,
2677
},
2678
a_struct: bevy_reflect::tests::SomeStruct {
2679
foo: "A Struct!",
2680
},
2681
a_tuple_struct: bevy_reflect::tests::SomeTupleStruct(
2682
"A Tuple Struct!",
2683
),
2684
enum_unit: A,
2685
enum_tuple: B(
2686
123,
2687
),
2688
enum_struct: C {
2689
value: 321,
2690
},
2691
custom: Cool debug!,
2692
}"#;
2693
2694
assert_eq!(expected, format!("\n{reflected:#?}"));
2695
}
2696
2697
#[test]
2698
fn multiple_reflect_lists() {
2699
#[derive(Hash, PartialEq, Reflect)]
2700
#[reflect(Debug, Hash)]
2701
#[reflect(PartialEq)]
2702
struct Foo(i32);
2703
2704
impl Debug for Foo {
2705
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
2706
write!(f, "Foo")
2707
}
2708
}
2709
2710
let foo = Foo(123);
2711
let foo: &dyn PartialReflect = &foo;
2712
2713
assert!(foo.reflect_hash().is_some());
2714
assert_eq!(Some(true), foo.reflect_partial_eq(foo));
2715
assert_eq!("Foo".to_string(), format!("{foo:?}"));
2716
}
2717
2718
#[test]
2719
fn custom_debug_function() {
2720
#[derive(Reflect)]
2721
#[reflect(Debug(custom_debug))]
2722
struct Foo {
2723
a: u32,
2724
}
2725
2726
fn custom_debug(_x: &Foo, f: &mut Formatter<'_>) -> core::fmt::Result {
2727
write!(f, "123")
2728
}
2729
2730
let foo = Foo { a: 1 };
2731
let foo: &dyn Reflect = &foo;
2732
2733
assert_eq!("123", format!("{foo:?}"));
2734
}
2735
2736
#[test]
2737
fn should_allow_custom_where() {
2738
#[derive(Reflect)]
2739
#[reflect(where T: Default)]
2740
struct Foo<T>(String, #[reflect(ignore)] PhantomData<T>);
2741
2742
#[derive(Default, TypePath)]
2743
struct Bar;
2744
2745
#[derive(TypePath)]
2746
struct Baz;
2747
2748
assert_impl_all!(Foo<Bar>: Reflect);
2749
assert_not_impl_all!(Foo<Baz>: Reflect);
2750
}
2751
2752
#[test]
2753
fn should_allow_empty_custom_where() {
2754
#[derive(Reflect)]
2755
#[reflect(where)]
2756
struct Foo<T>(String, #[reflect(ignore)] PhantomData<T>);
2757
2758
#[derive(TypePath)]
2759
struct Bar;
2760
2761
assert_impl_all!(Foo<Bar>: Reflect);
2762
}
2763
2764
#[test]
2765
fn should_allow_multiple_custom_where() {
2766
#[derive(Reflect)]
2767
#[reflect(where T: Default)]
2768
#[reflect(where U: core::ops::Add<T>)]
2769
struct Foo<T, U>(T, U);
2770
2771
#[allow(
2772
clippy::allow_attributes,
2773
dead_code,
2774
reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
2775
)]
2776
#[derive(Reflect)]
2777
struct Baz {
2778
a: Foo<i32, i32>,
2779
b: Foo<u32, u32>,
2780
}
2781
2782
assert_impl_all!(Foo<i32, i32>: Reflect);
2783
assert_not_impl_all!(Foo<i32, usize>: Reflect);
2784
}
2785
2786
#[test]
2787
fn should_allow_custom_where_with_assoc_type() {
2788
trait Trait {
2789
type Assoc;
2790
}
2791
2792
// We don't need `T` to be `Reflect` since we only care about `T::Assoc`
2793
#[derive(Reflect)]
2794
#[reflect(where T::Assoc: core::fmt::Display)]
2795
struct Foo<T: Trait>(T::Assoc);
2796
2797
#[derive(TypePath)]
2798
struct Bar;
2799
2800
impl Trait for Bar {
2801
type Assoc = usize;
2802
}
2803
2804
#[derive(TypePath)]
2805
struct Baz;
2806
2807
impl Trait for Baz {
2808
type Assoc = (f32, f32);
2809
}
2810
2811
assert_impl_all!(Foo<Bar>: Reflect);
2812
assert_not_impl_all!(Foo<Baz>: Reflect);
2813
}
2814
2815
#[test]
2816
fn should_allow_empty_enums() {
2817
#[derive(Reflect)]
2818
enum Empty {}
2819
2820
assert_impl_all!(Empty: Reflect);
2821
}
2822
2823
#[test]
2824
fn recursive_typed_storage_does_not_hang() {
2825
#[derive(Reflect)]
2826
struct Recurse<T>(T);
2827
2828
let _ = <Recurse<Recurse<()>> as Typed>::type_info();
2829
let _ = <Recurse<Recurse<()>> as TypePath>::type_path();
2830
2831
#[derive(Reflect)]
2832
#[reflect(no_field_bounds)]
2833
struct SelfRecurse {
2834
recurse: Vec<SelfRecurse>,
2835
}
2836
2837
let _ = <SelfRecurse as Typed>::type_info();
2838
let _ = <SelfRecurse as TypePath>::type_path();
2839
2840
#[derive(Reflect)]
2841
#[reflect(no_field_bounds)]
2842
enum RecurseA {
2843
Recurse(RecurseB),
2844
}
2845
2846
#[derive(Reflect)]
2847
// `#[reflect(no_field_bounds)]` not needed since already added to `RecurseA`
2848
struct RecurseB {
2849
vector: Vec<RecurseA>,
2850
}
2851
2852
let _ = <RecurseA as Typed>::type_info();
2853
let _ = <RecurseA as TypePath>::type_path();
2854
let _ = <RecurseB as Typed>::type_info();
2855
let _ = <RecurseB as TypePath>::type_path();
2856
}
2857
2858
#[test]
2859
fn recursive_registration_does_not_hang() {
2860
#[derive(Reflect)]
2861
struct Recurse<T>(T);
2862
2863
let mut registry = TypeRegistry::empty();
2864
2865
registry.register::<Recurse<Recurse<()>>>();
2866
2867
#[derive(Reflect)]
2868
#[reflect(no_field_bounds)]
2869
struct SelfRecurse {
2870
recurse: Vec<SelfRecurse>,
2871
}
2872
2873
registry.register::<SelfRecurse>();
2874
2875
#[derive(Reflect)]
2876
#[reflect(no_field_bounds)]
2877
enum RecurseA {
2878
Recurse(RecurseB),
2879
}
2880
2881
#[derive(Reflect)]
2882
struct RecurseB {
2883
vector: Vec<RecurseA>,
2884
}
2885
2886
registry.register::<RecurseA>();
2887
assert!(registry.contains(TypeId::of::<RecurseA>()));
2888
assert!(registry.contains(TypeId::of::<RecurseB>()));
2889
}
2890
2891
#[test]
2892
fn can_opt_out_type_path() {
2893
#[derive(Reflect)]
2894
#[reflect(type_path = false)]
2895
struct Foo<T> {
2896
#[reflect(ignore)]
2897
_marker: PhantomData<T>,
2898
}
2899
2900
struct NotTypePath;
2901
2902
impl<T: 'static> TypePath for Foo<T> {
2903
fn type_path() -> &'static str {
2904
core::any::type_name::<Self>()
2905
}
2906
2907
fn short_type_path() -> &'static str {
2908
static CELL: GenericTypePathCell = GenericTypePathCell::new();
2909
CELL.get_or_insert::<Self, _>(|| ShortName::of::<Self>().to_string())
2910
}
2911
2912
fn type_ident() -> Option<&'static str> {
2913
Some("Foo")
2914
}
2915
2916
fn crate_name() -> Option<&'static str> {
2917
Some("bevy_reflect")
2918
}
2919
2920
fn module_path() -> Option<&'static str> {
2921
Some("bevy_reflect::tests")
2922
}
2923
}
2924
2925
// Can use `TypePath`
2926
let path = <Foo<NotTypePath> as TypePath>::type_path();
2927
assert_eq!("bevy_reflect::tests::can_opt_out_type_path::Foo<bevy_reflect::tests::can_opt_out_type_path::NotTypePath>", path);
2928
2929
// Can register the type
2930
let mut registry = TypeRegistry::default();
2931
registry.register::<Foo<NotTypePath>>();
2932
2933
let registration = registry.get(TypeId::of::<Foo<NotTypePath>>()).unwrap();
2934
assert_eq!(
2935
"Foo<NotTypePath>",
2936
registration.type_info().type_path_table().short_path()
2937
);
2938
}
2939
2940
#[test]
2941
fn dynamic_types_debug_format() {
2942
#[derive(Debug, Reflect)]
2943
struct TestTupleStruct(u32);
2944
2945
#[derive(Debug, Reflect)]
2946
enum TestEnum {
2947
A(u32),
2948
B,
2949
}
2950
2951
#[derive(Debug, Reflect)]
2952
// test DynamicStruct
2953
struct TestStruct {
2954
// test DynamicTuple
2955
tuple: (u32, u32),
2956
// test DynamicTupleStruct
2957
tuple_struct: TestTupleStruct,
2958
// test DynamicList
2959
list: Vec<u32>,
2960
// test DynamicArray
2961
array: [u32; 3],
2962
// test DynamicEnum
2963
e: TestEnum,
2964
// test DynamicMap
2965
map: HashMap<u32, u32>,
2966
// test reflected value
2967
value: u32,
2968
}
2969
let mut map = <HashMap<_, _>>::default();
2970
map.insert(9, 10);
2971
let mut test_struct: DynamicStruct = TestStruct {
2972
tuple: (0, 1),
2973
list: vec![2, 3, 4],
2974
array: [5, 6, 7],
2975
tuple_struct: TestTupleStruct(8),
2976
e: TestEnum::A(11),
2977
map,
2978
value: 12,
2979
}
2980
.to_dynamic_struct();
2981
2982
// test unknown DynamicStruct
2983
let mut test_unknown_struct = DynamicStruct::default();
2984
test_unknown_struct.insert("a", 13);
2985
test_struct.insert("unknown_struct", test_unknown_struct);
2986
// test unknown DynamicTupleStruct
2987
let mut test_unknown_tuple_struct = DynamicTupleStruct::default();
2988
test_unknown_tuple_struct.insert(14);
2989
test_struct.insert("unknown_tuplestruct", test_unknown_tuple_struct);
2990
assert_eq!(
2991
format!("{test_struct:?}"),
2992
"DynamicStruct(bevy_reflect::tests::TestStruct { \
2993
tuple: DynamicTuple((0, 1)), \
2994
tuple_struct: DynamicTupleStruct(bevy_reflect::tests::TestTupleStruct(8)), \
2995
list: DynamicList([2, 3, 4]), \
2996
array: DynamicArray([5, 6, 7]), \
2997
e: DynamicEnum(A(11)), \
2998
map: DynamicMap({9: 10}), \
2999
value: 12, \
3000
unknown_struct: DynamicStruct(_ { a: 13 }), \
3001
unknown_tuplestruct: DynamicTupleStruct(_(14)) \
3002
})"
3003
);
3004
}
3005
3006
#[test]
3007
fn assert_impl_reflect_macro_on_all() {
3008
struct Struct {
3009
foo: (),
3010
}
3011
struct TupleStruct(());
3012
enum Enum {
3013
Foo { foo: () },
3014
Bar(()),
3015
}
3016
3017
impl_reflect!(
3018
#[type_path = "my_crate::foo"]
3019
struct Struct {
3020
foo: (),
3021
}
3022
);
3023
3024
impl_reflect!(
3025
#[type_path = "my_crate::foo"]
3026
struct TupleStruct(());
3027
);
3028
3029
impl_reflect!(
3030
#[type_path = "my_crate::foo"]
3031
enum Enum {
3032
Foo { foo: () },
3033
Bar(()),
3034
}
3035
);
3036
3037
assert_impl_all!(Struct: Reflect);
3038
assert_impl_all!(TupleStruct: Reflect);
3039
assert_impl_all!(Enum: Reflect);
3040
}
3041
3042
#[test]
3043
fn should_reflect_remote_type() {
3044
mod external_crate {
3045
use alloc::string::String;
3046
3047
#[derive(Debug, Default)]
3048
pub struct TheirType {
3049
pub value: String,
3050
}
3051
}
3052
3053
// === Remote Wrapper === //
3054
#[reflect_remote(external_crate::TheirType)]
3055
#[derive(Debug, Default)]
3056
#[reflect(Debug, Default)]
3057
struct MyType {
3058
pub value: String,
3059
}
3060
3061
let mut patch = DynamicStruct::default();
3062
patch.set_represented_type(Some(MyType::type_info()));
3063
patch.insert("value", "Goodbye".to_string());
3064
3065
let mut data = MyType(external_crate::TheirType {
3066
value: "Hello".to_string(),
3067
});
3068
3069
assert_eq!("Hello", data.0.value);
3070
data.apply(&patch);
3071
assert_eq!("Goodbye", data.0.value);
3072
3073
// === Struct Container === //
3074
#[derive(Reflect, Debug)]
3075
#[reflect(from_reflect = false)]
3076
struct ContainerStruct {
3077
#[reflect(remote = MyType)]
3078
their_type: external_crate::TheirType,
3079
}
3080
3081
let mut patch = DynamicStruct::default();
3082
patch.set_represented_type(Some(ContainerStruct::type_info()));
3083
patch.insert(
3084
"their_type",
3085
MyType(external_crate::TheirType {
3086
value: "Goodbye".to_string(),
3087
}),
3088
);
3089
3090
let mut data = ContainerStruct {
3091
their_type: external_crate::TheirType {
3092
value: "Hello".to_string(),
3093
},
3094
};
3095
3096
assert_eq!("Hello", data.their_type.value);
3097
data.apply(&patch);
3098
assert_eq!("Goodbye", data.their_type.value);
3099
3100
// === Tuple Struct Container === //
3101
#[derive(Reflect, Debug)]
3102
struct ContainerTupleStruct(#[reflect(remote = MyType)] external_crate::TheirType);
3103
3104
let mut patch = DynamicTupleStruct::default();
3105
patch.set_represented_type(Some(ContainerTupleStruct::type_info()));
3106
patch.insert(MyType(external_crate::TheirType {
3107
value: "Goodbye".to_string(),
3108
}));
3109
3110
let mut data = ContainerTupleStruct(external_crate::TheirType {
3111
value: "Hello".to_string(),
3112
});
3113
3114
assert_eq!("Hello", data.0.value);
3115
data.apply(&patch);
3116
assert_eq!("Goodbye", data.0.value);
3117
}
3118
3119
#[test]
3120
fn should_reflect_remote_value_type() {
3121
mod external_crate {
3122
use alloc::string::String;
3123
3124
#[derive(Clone, Debug, Default)]
3125
pub struct TheirType {
3126
pub value: String,
3127
}
3128
}
3129
3130
// === Remote Wrapper === //
3131
#[reflect_remote(external_crate::TheirType)]
3132
#[derive(Clone, Debug, Default)]
3133
#[reflect(opaque)]
3134
#[reflect(Debug, Default)]
3135
struct MyType {
3136
pub value: String,
3137
}
3138
3139
let mut data = MyType(external_crate::TheirType {
3140
value: "Hello".to_string(),
3141
});
3142
3143
let patch = MyType(external_crate::TheirType {
3144
value: "Goodbye".to_string(),
3145
});
3146
3147
assert_eq!("Hello", data.0.value);
3148
data.apply(&patch);
3149
assert_eq!("Goodbye", data.0.value);
3150
3151
// === Struct Container === //
3152
#[derive(Reflect, Debug)]
3153
#[reflect(from_reflect = false)]
3154
struct ContainerStruct {
3155
#[reflect(remote = MyType)]
3156
their_type: external_crate::TheirType,
3157
}
3158
3159
let mut patch = DynamicStruct::default();
3160
patch.set_represented_type(Some(ContainerStruct::type_info()));
3161
patch.insert(
3162
"their_type",
3163
MyType(external_crate::TheirType {
3164
value: "Goodbye".to_string(),
3165
}),
3166
);
3167
3168
let mut data = ContainerStruct {
3169
their_type: external_crate::TheirType {
3170
value: "Hello".to_string(),
3171
},
3172
};
3173
3174
assert_eq!("Hello", data.their_type.value);
3175
data.apply(&patch);
3176
assert_eq!("Goodbye", data.their_type.value);
3177
3178
// === Tuple Struct Container === //
3179
#[derive(Reflect, Debug)]
3180
struct ContainerTupleStruct(#[reflect(remote = MyType)] external_crate::TheirType);
3181
3182
let mut patch = DynamicTupleStruct::default();
3183
patch.set_represented_type(Some(ContainerTupleStruct::type_info()));
3184
patch.insert(MyType(external_crate::TheirType {
3185
value: "Goodbye".to_string(),
3186
}));
3187
3188
let mut data = ContainerTupleStruct(external_crate::TheirType {
3189
value: "Hello".to_string(),
3190
});
3191
3192
assert_eq!("Hello", data.0.value);
3193
data.apply(&patch);
3194
assert_eq!("Goodbye", data.0.value);
3195
}
3196
3197
#[test]
3198
fn should_reflect_remote_type_from_module() {
3199
mod wrapper {
3200
use super::*;
3201
3202
// We have to place this module internally to this one to get around the following error:
3203
// ```
3204
// error[E0433]: failed to resolve: use of undeclared crate or module `external_crate`
3205
// ```
3206
pub mod external_crate {
3207
use alloc::string::String;
3208
3209
#[allow(
3210
clippy::allow_attributes,
3211
dead_code,
3212
reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
3213
)]
3214
pub struct TheirType {
3215
pub value: String,
3216
}
3217
}
3218
3219
#[reflect_remote(external_crate::TheirType)]
3220
pub struct MyType {
3221
pub value: String,
3222
}
3223
}
3224
3225
#[allow(
3226
clippy::allow_attributes,
3227
dead_code,
3228
reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
3229
)]
3230
#[derive(Reflect)]
3231
struct ContainerStruct {
3232
#[reflect(remote = wrapper::MyType)]
3233
their_type: wrapper::external_crate::TheirType,
3234
}
3235
}
3236
3237
#[test]
3238
fn should_reflect_remote_enum() {
3239
mod external_crate {
3240
use alloc::string::String;
3241
3242
#[derive(Debug, PartialEq, Eq)]
3243
pub enum TheirType {
3244
Unit,
3245
Tuple(usize),
3246
Struct { value: String },
3247
}
3248
}
3249
3250
// === Remote Wrapper === //
3251
#[reflect_remote(external_crate::TheirType)]
3252
#[derive(Debug)]
3253
#[reflect(Debug)]
3254
enum MyType {
3255
Unit,
3256
Tuple(usize),
3257
Struct { value: String },
3258
}
3259
3260
let mut patch = DynamicEnum::from(MyType(external_crate::TheirType::Tuple(123)));
3261
3262
let mut data = MyType(external_crate::TheirType::Unit);
3263
3264
assert_eq!(external_crate::TheirType::Unit, data.0);
3265
data.apply(&patch);
3266
assert_eq!(external_crate::TheirType::Tuple(123), data.0);
3267
3268
patch = DynamicEnum::from(MyType(external_crate::TheirType::Struct {
3269
value: "Hello world!".to_string(),
3270
}));
3271
3272
data.apply(&patch);
3273
assert_eq!(
3274
external_crate::TheirType::Struct {
3275
value: "Hello world!".to_string()
3276
},
3277
data.0
3278
);
3279
3280
// === Enum Container === //
3281
#[derive(Reflect, Debug, PartialEq)]
3282
enum ContainerEnum {
3283
Foo,
3284
Bar {
3285
#[reflect(remote = MyType)]
3286
their_type: external_crate::TheirType,
3287
},
3288
}
3289
3290
let patch = DynamicEnum::from(ContainerEnum::Bar {
3291
their_type: external_crate::TheirType::Tuple(123),
3292
});
3293
3294
let mut data = ContainerEnum::Foo;
3295
3296
assert_eq!(ContainerEnum::Foo, data);
3297
data.apply(&patch);
3298
assert_eq!(
3299
ContainerEnum::Bar {
3300
their_type: external_crate::TheirType::Tuple(123)
3301
},
3302
data
3303
);
3304
}
3305
3306
#[test]
3307
fn should_reflect_nested_remote_type() {
3308
mod external_crate {
3309
pub struct TheirOuter<T> {
3310
pub a: TheirInner<T>,
3311
pub b: TheirInner<bool>,
3312
}
3313
3314
pub struct TheirInner<T>(pub T);
3315
}
3316
3317
#[reflect_remote(external_crate::TheirOuter<T>)]
3318
struct MyOuter<T: FromReflect + Reflectable> {
3319
#[reflect(remote = MyInner<T>)]
3320
pub a: external_crate::TheirInner<T>,
3321
#[reflect(remote = MyInner<bool>)]
3322
pub b: external_crate::TheirInner<bool>,
3323
}
3324
3325
#[reflect_remote(external_crate::TheirInner<T>)]
3326
struct MyInner<T: FromReflect>(pub T);
3327
3328
let mut patch = DynamicStruct::default();
3329
patch.set_represented_type(Some(MyOuter::<i32>::type_info()));
3330
patch.insert("a", MyInner(external_crate::TheirInner(321_i32)));
3331
patch.insert("b", MyInner(external_crate::TheirInner(true)));
3332
3333
let mut data = MyOuter(external_crate::TheirOuter {
3334
a: external_crate::TheirInner(123_i32),
3335
b: external_crate::TheirInner(false),
3336
});
3337
3338
assert_eq!(123, data.0.a.0);
3339
assert!(!data.0.b.0);
3340
data.apply(&patch);
3341
assert_eq!(321, data.0.a.0);
3342
assert!(data.0.b.0);
3343
}
3344
3345
#[test]
3346
fn should_reflect_nested_remote_enum() {
3347
mod external_crate {
3348
use core::fmt::Debug;
3349
3350
#[derive(Debug)]
3351
pub enum TheirOuter<T: Debug> {
3352
Unit,
3353
Tuple(TheirInner<T>),
3354
Struct { value: TheirInner<T> },
3355
}
3356
#[derive(Debug)]
3357
pub enum TheirInner<T: Debug> {
3358
Unit,
3359
Tuple(T),
3360
Struct { value: T },
3361
}
3362
}
3363
3364
#[reflect_remote(external_crate::TheirOuter<T>)]
3365
#[derive(Debug)]
3366
enum MyOuter<T: FromReflect + Reflectable + Debug> {
3367
Unit,
3368
Tuple(#[reflect(remote = MyInner<T>)] external_crate::TheirInner<T>),
3369
Struct {
3370
#[reflect(remote = MyInner<T>)]
3371
value: external_crate::TheirInner<T>,
3372
},
3373
}
3374
3375
#[reflect_remote(external_crate::TheirInner<T>)]
3376
#[derive(Debug)]
3377
enum MyInner<T: FromReflect + Debug> {
3378
Unit,
3379
Tuple(T),
3380
Struct { value: T },
3381
}
3382
3383
let mut patch = DynamicEnum::default();
3384
let mut value = DynamicStruct::default();
3385
value.insert("value", MyInner(external_crate::TheirInner::Tuple(123)));
3386
patch.set_variant("Struct", value);
3387
3388
let mut data = MyOuter(external_crate::TheirOuter::<i32>::Unit);
3389
3390
assert!(matches!(
3391
data,
3392
MyOuter(external_crate::TheirOuter::<i32>::Unit)
3393
));
3394
data.apply(&patch);
3395
assert!(matches!(
3396
data,
3397
MyOuter(external_crate::TheirOuter::Struct {
3398
value: external_crate::TheirInner::Tuple(123)
3399
})
3400
));
3401
}
3402
3403
#[test]
3404
fn should_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 Reflect> = Box::new(MyType(external_crate::TheirType {
3423
value: "Hello".to_string(),
3424
}));
3425
3426
let output: external_crate::TheirType = input
3427
.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_try_take_remote_type() {
3439
mod external_crate {
3440
use alloc::string::String;
3441
3442
#[derive(Debug, Default, PartialEq, Eq)]
3443
pub struct TheirType {
3444
pub value: String,
3445
}
3446
}
3447
3448
// === Remote Wrapper === //
3449
#[reflect_remote(external_crate::TheirType)]
3450
#[derive(Debug, Default)]
3451
#[reflect(Debug, Default)]
3452
struct MyType {
3453
pub value: String,
3454
}
3455
3456
let input: Box<dyn PartialReflect> = Box::new(MyType(external_crate::TheirType {
3457
value: "Hello".to_string(),
3458
}));
3459
3460
let output: external_crate::TheirType = input
3461
.try_take()
3462
.expect("should downcast to `external_crate::TheirType`");
3463
assert_eq!(
3464
external_crate::TheirType {
3465
value: "Hello".to_string(),
3466
},
3467
output,
3468
);
3469
}
3470
3471
#[test]
3472
fn should_take_nested_remote_type() {
3473
mod external_crate {
3474
#[derive(PartialEq, Eq, Debug)]
3475
pub struct TheirOuter<T> {
3476
pub inner: TheirInner<T>,
3477
}
3478
#[derive(PartialEq, Eq, Debug)]
3479
pub struct TheirInner<T>(pub T);
3480
}
3481
3482
#[reflect_remote(external_crate::TheirOuter<T>)]
3483
struct MyOuter<T: FromReflect + Reflectable> {
3484
#[reflect(remote = MyInner<T>)]
3485
pub inner: external_crate::TheirInner<T>,
3486
}
3487
3488
#[reflect_remote(external_crate::TheirInner<T>)]
3489
struct MyInner<T: FromReflect>(pub T);
3490
3491
let input: Box<dyn Reflect> = Box::new(MyOuter(external_crate::TheirOuter {
3492
inner: external_crate::TheirInner(123),
3493
}));
3494
3495
let output: external_crate::TheirOuter<i32> = input
3496
.take()
3497
.expect("should downcast to `external_crate::TheirOuter`");
3498
assert_eq!(
3499
external_crate::TheirOuter {
3500
inner: external_crate::TheirInner(123),
3501
},
3502
output
3503
);
3504
}
3505
3506
// https://github.com/bevyengine/bevy/issues/19017
3507
#[test]
3508
fn should_serialize_opaque_remote_type() {
3509
mod external_crate {
3510
use serde::{Deserialize, Serialize};
3511
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
3512
pub struct Vector2<T>(pub [T; 2]);
3513
}
3514
3515
#[reflect_remote(external_crate::Vector2<i32>)]
3516
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
3517
#[reflect(Serialize, Deserialize)]
3518
#[reflect(opaque)]
3519
struct Vector2Wrapper([i32; 2]);
3520
3521
#[derive(Reflect, Debug, PartialEq)]
3522
struct Point(#[reflect(remote = Vector2Wrapper)] external_crate::Vector2<i32>);
3523
3524
let point = Point(external_crate::Vector2([1, 2]));
3525
3526
let mut registry = TypeRegistry::new();
3527
registry.register::<Point>();
3528
registry.register::<Vector2Wrapper>();
3529
3530
let serializer = ReflectSerializer::new(&point, &registry);
3531
let serialized = ron::to_string(&serializer).unwrap();
3532
assert_eq!(serialized, r#"{"bevy_reflect::tests::Point":((((1,2))))}"#);
3533
3534
let mut deserializer = Deserializer::from_str(&serialized).unwrap();
3535
let reflect_deserializer = ReflectDeserializer::new(&registry);
3536
let deserialized = reflect_deserializer.deserialize(&mut deserializer).unwrap();
3537
let point = <Point as FromReflect>::from_reflect(&*deserialized).unwrap();
3538
assert_eq!(point, Point(external_crate::Vector2([1, 2])));
3539
}
3540
3541
#[cfg(feature = "auto_register")]
3542
mod auto_register_reflect {
3543
use super::*;
3544
3545
#[test]
3546
fn should_ignore_auto_reflect_registration() {
3547
#[derive(Reflect)]
3548
#[reflect(no_auto_register)]
3549
struct NoAutomaticStruct {
3550
a: usize,
3551
}
3552
3553
let mut registry = TypeRegistry::default();
3554
registry.register_derived_types();
3555
3556
assert!(!registry.contains(TypeId::of::<NoAutomaticStruct>()));
3557
}
3558
3559
#[test]
3560
fn should_auto_register_reflect_for_all_supported_types() {
3561
// Struct
3562
#[derive(Reflect)]
3563
struct StructReflect {
3564
a: usize,
3565
}
3566
3567
// ZST struct
3568
#[derive(Reflect)]
3569
struct ZSTStructReflect;
3570
3571
// Tuple struct
3572
#[derive(Reflect)]
3573
struct TupleStructReflect(pub u32);
3574
3575
// Enum
3576
#[derive(Reflect)]
3577
enum EnumReflect {
3578
A,
3579
B,
3580
}
3581
3582
// ZST enum
3583
#[derive(Reflect)]
3584
enum ZSTEnumReflect {}
3585
3586
// Opaque struct
3587
#[derive(Reflect, Clone)]
3588
#[reflect(opaque)]
3589
struct OpaqueStructReflect {
3590
_a: usize,
3591
}
3592
3593
// ZST opaque struct
3594
#[derive(Reflect, Clone)]
3595
#[reflect(opaque)]
3596
struct ZSTOpaqueStructReflect;
3597
3598
let mut registry = TypeRegistry::default();
3599
registry.register_derived_types();
3600
3601
assert!(registry.contains(TypeId::of::<StructReflect>()));
3602
assert!(registry.contains(TypeId::of::<ZSTStructReflect>()));
3603
assert!(registry.contains(TypeId::of::<TupleStructReflect>()));
3604
assert!(registry.contains(TypeId::of::<EnumReflect>()));
3605
assert!(registry.contains(TypeId::of::<ZSTEnumReflect>()));
3606
assert!(registry.contains(TypeId::of::<OpaqueStructReflect>()));
3607
assert!(registry.contains(TypeId::of::<ZSTOpaqueStructReflect>()));
3608
}
3609
}
3610
3611
#[cfg(feature = "glam")]
3612
mod glam {
3613
use super::*;
3614
use ::glam::{quat, vec3, Quat, Vec3};
3615
3616
#[test]
3617
fn quat_serialization() {
3618
let q = quat(1.0, 2.0, 3.0, 4.0);
3619
3620
let mut registry = TypeRegistry::default();
3621
registry.register::<f32>();
3622
registry.register::<Quat>();
3623
3624
let ser = ReflectSerializer::new(&q, &registry);
3625
3626
let config = PrettyConfig::default()
3627
.new_line(String::from("\n"))
3628
.indentor(String::from(" "));
3629
let output = to_string_pretty(&ser, config).unwrap();
3630
let expected = r#"
3631
{
3632
"glam::Quat": (1.0, 2.0, 3.0, 4.0),
3633
}"#;
3634
3635
assert_eq!(expected, format!("\n{output}"));
3636
}
3637
3638
#[test]
3639
fn quat_deserialization() {
3640
let data = r#"
3641
{
3642
"glam::Quat": (1.0, 2.0, 3.0, 4.0),
3643
}"#;
3644
3645
let mut registry = TypeRegistry::default();
3646
registry.register::<Quat>();
3647
registry.register::<f32>();
3648
3649
let de = ReflectDeserializer::new(&registry);
3650
3651
let mut deserializer =
3652
Deserializer::from_str(data).expect("Failed to acquire deserializer");
3653
3654
let dynamic_struct = de
3655
.deserialize(&mut deserializer)
3656
.expect("Failed to deserialize");
3657
3658
let mut result = Quat::default();
3659
3660
result.apply(dynamic_struct.as_partial_reflect());
3661
3662
assert_eq!(result, quat(1.0, 2.0, 3.0, 4.0));
3663
}
3664
3665
#[test]
3666
fn vec3_serialization() {
3667
let v = vec3(12.0, 3.0, -6.9);
3668
3669
let mut registry = TypeRegistry::default();
3670
registry.register::<f32>();
3671
registry.register::<Vec3>();
3672
3673
let ser = ReflectSerializer::new(&v, &registry);
3674
3675
let config = PrettyConfig::default()
3676
.new_line(String::from("\n"))
3677
.indentor(String::from(" "));
3678
let output = to_string_pretty(&ser, config).unwrap();
3679
let expected = r#"
3680
{
3681
"glam::Vec3": (12.0, 3.0, -6.9),
3682
}"#;
3683
3684
assert_eq!(expected, format!("\n{output}"));
3685
}
3686
3687
#[test]
3688
fn vec3_deserialization() {
3689
let data = r#"
3690
{
3691
"glam::Vec3": (12.0, 3.0, -6.9),
3692
}"#;
3693
3694
let mut registry = TypeRegistry::default();
3695
registry.add_registration(Vec3::get_type_registration());
3696
registry.add_registration(f32::get_type_registration());
3697
3698
let de = ReflectDeserializer::new(&registry);
3699
3700
let mut deserializer =
3701
Deserializer::from_str(data).expect("Failed to acquire deserializer");
3702
3703
let dynamic_struct = de
3704
.deserialize(&mut deserializer)
3705
.expect("Failed to deserialize");
3706
3707
let mut result = Vec3::default();
3708
3709
result.apply(dynamic_struct.as_partial_reflect());
3710
3711
assert_eq!(result, vec3(12.0, 3.0, -6.9));
3712
}
3713
3714
#[test]
3715
fn vec3_field_access() {
3716
let mut v = vec3(1.0, 2.0, 3.0);
3717
3718
assert_eq!(*v.get_field::<f32>("x").unwrap(), 1.0);
3719
3720
*v.get_field_mut::<f32>("y").unwrap() = 6.0;
3721
3722
assert_eq!(v.y, 6.0);
3723
}
3724
3725
#[test]
3726
fn vec3_path_access() {
3727
let mut v = vec3(1.0, 2.0, 3.0);
3728
3729
assert_eq!(
3730
*v.reflect_path("x")
3731
.unwrap()
3732
.try_downcast_ref::<f32>()
3733
.unwrap(),
3734
1.0
3735
);
3736
3737
*v.reflect_path_mut("y")
3738
.unwrap()
3739
.try_downcast_mut::<f32>()
3740
.unwrap() = 6.0;
3741
3742
assert_eq!(v.y, 6.0);
3743
}
3744
3745
#[test]
3746
fn vec3_apply_dynamic() {
3747
let mut v = vec3(3.0, 3.0, 3.0);
3748
3749
let mut d = DynamicStruct::default();
3750
d.insert("x", 4.0f32);
3751
d.insert("y", 2.0f32);
3752
d.insert("z", 1.0f32);
3753
3754
v.apply(&d);
3755
3756
assert_eq!(v, vec3(4.0, 2.0, 1.0));
3757
}
3758
}
3759
}
3760
3761