Skip to content

Implement FromIterator/IntoIterator for dynamic types #14250

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 42 additions & 13 deletions crates/bevy_reflect/src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,20 +192,9 @@ impl DynamicArray {
}
}

#[deprecated(since = "0.15.0", note = "use from_values")]
#[deprecated(since = "0.15.0", note = "use from_iter")]
pub fn from_vec<T: Reflect>(values: Vec<T>) -> Self {
Self::from_values(values)
}

pub fn from_values<T: Reflect>(values: impl IntoIterator<Item = T>) -> Self {
Self {
represented_type: None,
values: values
.into_iter()
.map(|field| Box::new(field) as Box<dyn Reflect>)
.collect::<Vec<_>>()
.into_boxed_slice(),
}
Self::from_iter(values)
}

/// Sets the [type] to be represented by this `DynamicArray`.
Expand Down Expand Up @@ -363,6 +352,46 @@ impl Array for DynamicArray {
}
}

impl FromIterator<Box<dyn Reflect>> for DynamicArray {
fn from_iter<I: IntoIterator<Item = Box<dyn Reflect>>>(values: I) -> Self {
Self {
represented_type: None,
values: values.into_iter().collect::<Vec<_>>().into_boxed_slice(),
}
}
}

impl<T: Reflect> FromIterator<T> for DynamicArray {
fn from_iter<I: IntoIterator<Item = T>>(values: I) -> Self {
Self {
represented_type: None,
values: values
.into_iter()
.map(|field| Box::new(field) as Box<dyn Reflect>)
.collect::<Vec<_>>()
.into_boxed_slice(),
}
}
}

impl IntoIterator for DynamicArray {
type Item = Box<dyn Reflect>;
type IntoIter = std::vec::IntoIter<Self::Item>;

fn into_iter(self) -> Self::IntoIter {
Box::into_iter(self.values)
}
}

impl<'a> IntoIterator for &'a DynamicArray {
type Item = &'a dyn Reflect;
type IntoIter = ArrayIter<'a>;

fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}

impl_type_path!((in bevy_reflect) DynamicArray);
impl_function_traits!(DynamicArray);
/// An iterator over an [`Array`].
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_reflect/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1088,7 +1088,7 @@ mod tests {
});
foo_patch.insert("g", composite);

let array = DynamicArray::from_values([2u32, 2u32]);
let array = DynamicArray::from_iter([2u32, 2u32]);
foo_patch.insert("h", array);

foo.apply(&foo_patch);
Expand Down
30 changes: 30 additions & 0 deletions crates/bevy_reflect/src/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,27 @@ impl Debug for DynamicList {
}
}

impl FromIterator<Box<dyn Reflect>> for DynamicList {
fn from_iter<I: IntoIterator<Item = Box<dyn Reflect>>>(values: I) -> Self {
Self {
represented_type: None,
values: values.into_iter().collect(),
}
}
}

impl<T: Reflect> FromIterator<T> for DynamicList {
fn from_iter<I: IntoIterator<Item = T>>(values: I) -> Self {
Self {
represented_type: None,
values: values
.into_iter()
.map(|field| Box::new(field) as Box<dyn Reflect>)
.collect(),
}
}
}

impl IntoIterator for DynamicList {
type Item = Box<dyn Reflect>;
type IntoIter = std::vec::IntoIter<Self::Item>;
Expand All @@ -387,6 +408,15 @@ impl IntoIterator for DynamicList {
}
}

impl<'a> IntoIterator for &'a DynamicList {
type Item = &'a dyn Reflect;
type IntoIter = ListIter<'a>;

fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}

/// An iterator over an [`List`].
pub struct ListIter<'a> {
list: &'a dyn List,
Expand Down
29 changes: 29 additions & 0 deletions crates/bevy_reflect/src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,26 @@ impl<'a> Iterator for MapIter<'a> {
}
}

impl FromIterator<(Box<dyn Reflect>, Box<dyn Reflect>)> for DynamicMap {
fn from_iter<I: IntoIterator<Item = (Box<dyn Reflect>, Box<dyn Reflect>)>>(items: I) -> Self {
let mut dynamic_map = Self::default();
for (key, value) in items.into_iter() {
dynamic_map.insert_boxed(key, value);
}
dynamic_map
}
}

impl<K: Reflect, V: Reflect> FromIterator<(K, V)> for DynamicMap {
fn from_iter<I: IntoIterator<Item = (K, V)>>(items: I) -> Self {
let mut map = Self::default();
for (key, value) in items.into_iter() {
map.insert(key, value);
}
map
}
}

impl IntoIterator for DynamicMap {
type Item = (Box<dyn Reflect>, Box<dyn Reflect>);
type IntoIter = std::vec::IntoIter<Self::Item>;
Expand All @@ -464,6 +484,15 @@ impl IntoIterator for DynamicMap {
}
}

impl<'a> IntoIterator for &'a DynamicMap {
type Item = (&'a dyn Reflect, &'a dyn Reflect);
type IntoIter = MapIter<'a>;

fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}

impl<'a> ExactSizeIterator for MapIter<'a> {}

/// Compares a [`Map`] with a [`Reflect`] value.
Expand Down
38 changes: 38 additions & 0 deletions crates/bevy_reflect/src/struct_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,44 @@ impl Debug for DynamicStruct {
}
}

impl FromIterator<(String, Box<dyn Reflect>)> for DynamicStruct {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are cool! I've been wanting a succinct way to create DynamicStruct and friends for a long time haha

fn from_iter<I: IntoIterator<Item = (String, Box<dyn Reflect>)>>(fields: I) -> Self {
let mut dynamic_struct = Self::default();
for (name, value) in fields.into_iter() {
dynamic_struct.insert_boxed(name, value);
}
dynamic_struct
}
}

impl<V: Reflect> FromIterator<(String, V)> for DynamicStruct {
fn from_iter<I: IntoIterator<Item = (String, V)>>(fields: I) -> Self {
let mut dynamic_struct = Self::default();
for (name, value) in fields.into_iter() {
dynamic_struct.insert(name, value);
}
dynamic_struct
}
}

impl IntoIterator for DynamicStruct {
type Item = Box<dyn Reflect>;
type IntoIter = std::vec::IntoIter<Self::Item>;

fn into_iter(self) -> Self::IntoIter {
self.fields.into_iter()
}
}

impl<'a> IntoIterator for &'a DynamicStruct {
type Item = &'a dyn Reflect;
type IntoIter = FieldIter<'a>;

fn into_iter(self) -> Self::IntoIter {
self.iter_fields()
}
}

/// Compares a [`Struct`] with a [`Reflect`] value.
///
/// Returns true if and only if all of the following are true:
Expand Down
39 changes: 39 additions & 0 deletions crates/bevy_reflect/src/tuple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,45 @@ impl Reflect for DynamicTuple {

impl_type_path!((in bevy_reflect) DynamicTuple);

impl FromIterator<Box<dyn Reflect>> for DynamicTuple {
fn from_iter<I: IntoIterator<Item = Box<dyn Reflect>>>(fields: I) -> Self {
Self {
represented_type: None,
fields: fields.into_iter().collect(),
}
}
}

impl<T: Reflect> FromIterator<T> for DynamicTuple {
fn from_iter<I: IntoIterator<Item = T>>(values: I) -> Self {
Self {
represented_type: None,
fields: values
.into_iter()
.map(|field| Box::new(field) as Box<dyn Reflect>)
.collect(),
}
}
}

impl IntoIterator for DynamicTuple {
type Item = Box<dyn Reflect>;
type IntoIter = std::vec::IntoIter<Self::Item>;

fn into_iter(self) -> Self::IntoIter {
self.fields.into_iter()
}
}

impl<'a> IntoIterator for &'a DynamicTuple {
type Item = &'a dyn Reflect;
type IntoIter = TupleFieldIter<'a>;

fn into_iter(self) -> Self::IntoIter {
self.iter_fields()
}
}

/// Applies the elements of `b` to the corresponding elements of `a`.
///
/// # Panics
Expand Down
39 changes: 39 additions & 0 deletions crates/bevy_reflect/src/tuple_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,45 @@ impl From<DynamicTuple> for DynamicTupleStruct {
}
}

impl FromIterator<Box<dyn Reflect>> for DynamicTupleStruct {
fn from_iter<I: IntoIterator<Item = Box<dyn Reflect>>>(fields: I) -> Self {
Self {
represented_type: None,
fields: fields.into_iter().collect(),
}
}
}

impl<T: Reflect> FromIterator<T> for DynamicTupleStruct {
fn from_iter<I: IntoIterator<Item = T>>(fields: I) -> Self {
Self {
represented_type: None,
fields: fields
.into_iter()
.map(|field| Box::new(field) as Box<dyn Reflect>)
.collect(),
}
}
}

impl IntoIterator for DynamicTupleStruct {
type Item = Box<dyn Reflect>;
type IntoIter = std::vec::IntoIter<Self::Item>;

fn into_iter(self) -> Self::IntoIter {
self.fields.into_iter()
}
}

impl<'a> IntoIterator for &'a DynamicTupleStruct {
type Item = &'a dyn Reflect;
type IntoIter = TupleStructFieldIter<'a>;

fn into_iter(self) -> Self::IntoIter {
self.iter_fields()
}
}

/// Compares a [`TupleStruct`] with a [`Reflect`] value.
///
/// Returns true if and only if all of the following are true:
Expand Down
2 changes: 1 addition & 1 deletion examples/reflection/dynamic_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ fn main() {

// 2. `DynamicArray`
{
let dynamic_array = DynamicArray::from_values([1u32, 2u32, 3u32]);
let dynamic_array = DynamicArray::from_iter([1u32, 2u32, 3u32]);

let mut my_array = [0u32; 3];
my_array.apply(&dynamic_array);
Expand Down
Loading