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
Changes from all commits
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
46 changes: 38 additions & 8 deletions crates/bevy_reflect/src/array.rs
Original file line number Diff line number Diff line change
@@ -192,15 +192,9 @@ impl DynamicArray {
}
}

#[deprecated(since = "0.15.0", note = "use from_iter")]
pub fn from_vec<T: Reflect>(values: Vec<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`.
@@ -358,6 +352,42 @@ 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 {
values
.into_iter()
.map(|value| Box::new(value).into_reflect())
.collect()
}
}

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

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

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`].
2 changes: 1 addition & 1 deletion crates/bevy_reflect/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1088,7 +1088,7 @@ mod tests {
});
foo_patch.insert("g", composite);

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

foo.apply(&foo_patch);
27 changes: 27 additions & 0 deletions crates/bevy_reflect/src/list.rs
Original file line number Diff line number Diff line change
@@ -378,6 +378,24 @@ 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 {
values
.into_iter()
.map(|field| Box::new(field).into_reflect())
.collect()
}
}

impl IntoIterator for DynamicList {
type Item = Box<dyn Reflect>;
type IntoIter = std::vec::IntoIter<Self::Item>;
@@ -387,6 +405,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,
29 changes: 29 additions & 0 deletions crates/bevy_reflect/src/map.rs
Original file line number Diff line number Diff line change
@@ -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 map = Self::default();
for (key, value) in items.into_iter() {
map.insert_boxed(key, value);
}
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>;
@@ -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.
33 changes: 33 additions & 0 deletions crates/bevy_reflect/src/struct_trait.rs
Original file line number Diff line number Diff line change
@@ -508,6 +508,39 @@ impl Debug for DynamicStruct {
}
}

impl<'a, N> FromIterator<(N, Box<dyn Reflect>)> for DynamicStruct
where
N: Into<Cow<'a, str>>,
{
/// Create a dynamic struct that doesn't represent a type from the
/// field name, field value pairs.
fn from_iter<I: IntoIterator<Item = (N, 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 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:
27 changes: 27 additions & 0 deletions crates/bevy_reflect/src/tuple.rs
Original file line number Diff line number Diff line change
@@ -391,6 +391,33 @@ 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 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
27 changes: 27 additions & 0 deletions crates/bevy_reflect/src/tuple_struct.rs
Original file line number Diff line number Diff line change
@@ -426,6 +426,33 @@ 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 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:
17 changes: 4 additions & 13 deletions examples/reflection/dynamic_types.rs
Original file line number Diff line number Diff line change
@@ -135,10 +135,7 @@ fn main() {
// Lastly, while dynamic types are commonly generated via reflection methods like
// `Reflect::clone_value` or via the reflection deserializers,
// you can also construct them manually.
let mut my_dynamic_list = DynamicList::default();
my_dynamic_list.push(1u32);
my_dynamic_list.push(2u32);
my_dynamic_list.push(3u32);
let mut my_dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);

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

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

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

// 3. `DynamicList`
{
let mut dynamic_list = DynamicList::default();
dynamic_list.push(1u32);
dynamic_list.push(2u32);
dynamic_list.push(3u32);
let dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);

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

// 4. `DynamicMap`
{
let mut dynamic_map = DynamicMap::default();
dynamic_map.insert("x", 1u32);
dynamic_map.insert("y", 2u32);
dynamic_map.insert("z", 3u32);
let dynamic_map = DynamicMap::from_iter([("x", 1u32), ("y", 2u32), ("z", 3u32)]);

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