Skip to content

Commit ab255ae

Browse files
Implement FromIterator/IntoIterator for dynamic types (#14250)
# Objective Implement FromIterator/IntoIterator for dynamic types where missing Note: - can't impl `IntoIterator` for `&Array` & co because of orphan rules - `into_iter().collect()` is a no-op for `Vec`s because of specialization --- ## Migration Guide - Change `DynamicArray::from_vec` to `DynamicArray::from_iter`
1 parent 18abe21 commit ab255ae

File tree

8 files changed

+186
-22
lines changed

8 files changed

+186
-22
lines changed

crates/bevy_reflect/src/array.rs

+38-8
Original file line numberDiff line numberDiff line change
@@ -203,15 +203,9 @@ impl DynamicArray {
203203
}
204204
}
205205

206+
#[deprecated(since = "0.15.0", note = "use from_iter")]
206207
pub fn from_vec<T: Reflect>(values: Vec<T>) -> Self {
207-
Self {
208-
represented_type: None,
209-
values: values
210-
.into_iter()
211-
.map(|field| Box::new(field) as Box<dyn Reflect>)
212-
.collect::<Vec<_>>()
213-
.into_boxed_slice(),
214-
}
208+
Self::from_iter(values)
215209
}
216210

217211
/// Sets the [type] to be represented by this `DynamicArray`.
@@ -369,6 +363,42 @@ impl Array for DynamicArray {
369363
}
370364
}
371365

366+
impl FromIterator<Box<dyn Reflect>> for DynamicArray {
367+
fn from_iter<I: IntoIterator<Item = Box<dyn Reflect>>>(values: I) -> Self {
368+
Self {
369+
represented_type: None,
370+
values: values.into_iter().collect::<Vec<_>>().into_boxed_slice(),
371+
}
372+
}
373+
}
374+
375+
impl<T: Reflect> FromIterator<T> for DynamicArray {
376+
fn from_iter<I: IntoIterator<Item = T>>(values: I) -> Self {
377+
values
378+
.into_iter()
379+
.map(|value| Box::new(value).into_reflect())
380+
.collect()
381+
}
382+
}
383+
384+
impl IntoIterator for DynamicArray {
385+
type Item = Box<dyn Reflect>;
386+
type IntoIter = std::vec::IntoIter<Self::Item>;
387+
388+
fn into_iter(self) -> Self::IntoIter {
389+
self.values.into_vec().into_iter()
390+
}
391+
}
392+
393+
impl<'a> IntoIterator for &'a DynamicArray {
394+
type Item = &'a dyn Reflect;
395+
type IntoIter = ArrayIter<'a>;
396+
397+
fn into_iter(self) -> Self::IntoIter {
398+
self.iter()
399+
}
400+
}
401+
372402
impl_type_path!((in bevy_reflect) DynamicArray);
373403
#[cfg(feature = "functions")]
374404
crate::func::macros::impl_function_traits!(DynamicArray);

crates/bevy_reflect/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1092,7 +1092,7 @@ mod tests {
10921092
});
10931093
foo_patch.insert("g", composite);
10941094

1095-
let array = DynamicArray::from_vec(vec![2u32, 2u32]);
1095+
let array = DynamicArray::from_iter([2u32, 2u32]);
10961096
foo_patch.insert("h", array);
10971097

10981098
foo.apply(&foo_patch);

crates/bevy_reflect/src/list.rs

+27
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,24 @@ impl Debug for DynamicList {
388388
}
389389
}
390390

391+
impl FromIterator<Box<dyn Reflect>> for DynamicList {
392+
fn from_iter<I: IntoIterator<Item = Box<dyn Reflect>>>(values: I) -> Self {
393+
Self {
394+
represented_type: None,
395+
values: values.into_iter().collect(),
396+
}
397+
}
398+
}
399+
400+
impl<T: Reflect> FromIterator<T> for DynamicList {
401+
fn from_iter<I: IntoIterator<Item = T>>(values: I) -> Self {
402+
values
403+
.into_iter()
404+
.map(|field| Box::new(field).into_reflect())
405+
.collect()
406+
}
407+
}
408+
391409
impl IntoIterator for DynamicList {
392410
type Item = Box<dyn Reflect>;
393411
type IntoIter = std::vec::IntoIter<Self::Item>;
@@ -397,6 +415,15 @@ impl IntoIterator for DynamicList {
397415
}
398416
}
399417

418+
impl<'a> IntoIterator for &'a DynamicList {
419+
type Item = &'a dyn Reflect;
420+
type IntoIter = ListIter<'a>;
421+
422+
fn into_iter(self) -> Self::IntoIter {
423+
self.iter()
424+
}
425+
}
426+
400427
/// An iterator over an [`List`].
401428
pub struct ListIter<'a> {
402429
list: &'a dyn List,

crates/bevy_reflect/src/map.rs

+29
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,26 @@ impl<'a> Iterator for MapIter<'a> {
478478
}
479479
}
480480

481+
impl FromIterator<(Box<dyn Reflect>, Box<dyn Reflect>)> for DynamicMap {
482+
fn from_iter<I: IntoIterator<Item = (Box<dyn Reflect>, Box<dyn Reflect>)>>(items: I) -> Self {
483+
let mut map = Self::default();
484+
for (key, value) in items.into_iter() {
485+
map.insert_boxed(key, value);
486+
}
487+
map
488+
}
489+
}
490+
491+
impl<K: Reflect, V: Reflect> FromIterator<(K, V)> for DynamicMap {
492+
fn from_iter<I: IntoIterator<Item = (K, V)>>(items: I) -> Self {
493+
let mut map = Self::default();
494+
for (key, value) in items.into_iter() {
495+
map.insert(key, value);
496+
}
497+
map
498+
}
499+
}
500+
481501
impl IntoIterator for DynamicMap {
482502
type Item = (Box<dyn Reflect>, Box<dyn Reflect>);
483503
type IntoIter = std::vec::IntoIter<Self::Item>;
@@ -487,6 +507,15 @@ impl IntoIterator for DynamicMap {
487507
}
488508
}
489509

510+
impl<'a> IntoIterator for &'a DynamicMap {
511+
type Item = (&'a dyn Reflect, &'a dyn Reflect);
512+
type IntoIter = MapIter<'a>;
513+
514+
fn into_iter(self) -> Self::IntoIter {
515+
self.iter()
516+
}
517+
}
518+
490519
impl<'a> ExactSizeIterator for MapIter<'a> {}
491520

492521
/// Compares a [`Map`] with a [`Reflect`] value.

crates/bevy_reflect/src/struct_trait.rs

+33
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,39 @@ impl Debug for DynamicStruct {
508508
}
509509
}
510510

511+
impl<'a, N> FromIterator<(N, Box<dyn Reflect>)> for DynamicStruct
512+
where
513+
N: Into<Cow<'a, str>>,
514+
{
515+
/// Create a dynamic struct that doesn't represent a type from the
516+
/// field name, field value pairs.
517+
fn from_iter<I: IntoIterator<Item = (N, Box<dyn Reflect>)>>(fields: I) -> Self {
518+
let mut dynamic_struct = Self::default();
519+
for (name, value) in fields.into_iter() {
520+
dynamic_struct.insert_boxed(name, value);
521+
}
522+
dynamic_struct
523+
}
524+
}
525+
526+
impl IntoIterator for DynamicStruct {
527+
type Item = Box<dyn Reflect>;
528+
type IntoIter = std::vec::IntoIter<Self::Item>;
529+
530+
fn into_iter(self) -> Self::IntoIter {
531+
self.fields.into_iter()
532+
}
533+
}
534+
535+
impl<'a> IntoIterator for &'a DynamicStruct {
536+
type Item = &'a dyn Reflect;
537+
type IntoIter = FieldIter<'a>;
538+
539+
fn into_iter(self) -> Self::IntoIter {
540+
self.iter_fields()
541+
}
542+
}
543+
511544
/// Compares a [`Struct`] with a [`Reflect`] value.
512545
///
513546
/// Returns true if and only if all of the following are true:

crates/bevy_reflect/src/tuple.rs

+27
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,33 @@ impl Reflect for DynamicTuple {
391391

392392
impl_type_path!((in bevy_reflect) DynamicTuple);
393393

394+
impl FromIterator<Box<dyn Reflect>> for DynamicTuple {
395+
fn from_iter<I: IntoIterator<Item = Box<dyn Reflect>>>(fields: I) -> Self {
396+
Self {
397+
represented_type: None,
398+
fields: fields.into_iter().collect(),
399+
}
400+
}
401+
}
402+
403+
impl IntoIterator for DynamicTuple {
404+
type Item = Box<dyn Reflect>;
405+
type IntoIter = std::vec::IntoIter<Self::Item>;
406+
407+
fn into_iter(self) -> Self::IntoIter {
408+
self.fields.into_iter()
409+
}
410+
}
411+
412+
impl<'a> IntoIterator for &'a DynamicTuple {
413+
type Item = &'a dyn Reflect;
414+
type IntoIter = TupleFieldIter<'a>;
415+
416+
fn into_iter(self) -> Self::IntoIter {
417+
self.iter_fields()
418+
}
419+
}
420+
394421
/// Applies the elements of `b` to the corresponding elements of `a`.
395422
///
396423
/// # Panics

crates/bevy_reflect/src/tuple_struct.rs

+27
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,33 @@ impl From<DynamicTuple> for DynamicTupleStruct {
426426
}
427427
}
428428

429+
impl FromIterator<Box<dyn Reflect>> for DynamicTupleStruct {
430+
fn from_iter<I: IntoIterator<Item = Box<dyn Reflect>>>(fields: I) -> Self {
431+
Self {
432+
represented_type: None,
433+
fields: fields.into_iter().collect(),
434+
}
435+
}
436+
}
437+
438+
impl IntoIterator for DynamicTupleStruct {
439+
type Item = Box<dyn Reflect>;
440+
type IntoIter = std::vec::IntoIter<Self::Item>;
441+
442+
fn into_iter(self) -> Self::IntoIter {
443+
self.fields.into_iter()
444+
}
445+
}
446+
447+
impl<'a> IntoIterator for &'a DynamicTupleStruct {
448+
type Item = &'a dyn Reflect;
449+
type IntoIter = TupleStructFieldIter<'a>;
450+
451+
fn into_iter(self) -> Self::IntoIter {
452+
self.iter_fields()
453+
}
454+
}
455+
429456
/// Compares a [`TupleStruct`] with a [`Reflect`] value.
430457
///
431458
/// Returns true if and only if all of the following are true:

examples/reflection/dynamic_types.rs

+4-13
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,7 @@ fn main() {
135135
// Lastly, while dynamic types are commonly generated via reflection methods like
136136
// `Reflect::clone_value` or via the reflection deserializers,
137137
// you can also construct them manually.
138-
let mut my_dynamic_list = DynamicList::default();
139-
my_dynamic_list.push(1u32);
140-
my_dynamic_list.push(2u32);
141-
my_dynamic_list.push(3u32);
138+
let mut my_dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
142139

143140
// This is useful when you just need to apply some subset of changes to a type.
144141
let mut my_list: Vec<u32> = Vec::new();
@@ -167,7 +164,7 @@ fn main() {
167164

168165
// 2. `DynamicArray`
169166
{
170-
let dynamic_array = DynamicArray::from_vec(vec![1u32, 2u32, 3u32]);
167+
let dynamic_array = DynamicArray::from_iter([1u32, 2u32, 3u32]);
171168

172169
let mut my_array = [0u32; 3];
173170
my_array.apply(&dynamic_array);
@@ -176,10 +173,7 @@ fn main() {
176173

177174
// 3. `DynamicList`
178175
{
179-
let mut dynamic_list = DynamicList::default();
180-
dynamic_list.push(1u32);
181-
dynamic_list.push(2u32);
182-
dynamic_list.push(3u32);
176+
let dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
183177

184178
let mut my_list: Vec<u32> = Vec::new();
185179
my_list.apply(&dynamic_list);
@@ -188,10 +182,7 @@ fn main() {
188182

189183
// 4. `DynamicMap`
190184
{
191-
let mut dynamic_map = DynamicMap::default();
192-
dynamic_map.insert("x", 1u32);
193-
dynamic_map.insert("y", 2u32);
194-
dynamic_map.insert("z", 3u32);
185+
let dynamic_map = DynamicMap::from_iter([("x", 1u32), ("y", 2u32), ("z", 3u32)]);
195186

196187
let mut my_map: HashMap<&str, u32> = HashMap::new();
197188
my_map.apply(&dynamic_map);

0 commit comments

Comments
 (0)