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