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 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
Expand Up @@ -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`.
Expand Down Expand Up @@ -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`].
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_vec(vec![2u32, 2u32]);
let array = DynamicArray::from_iter([2u32, 2u32]);
foo_patch.insert("h", array);

foo.apply(&foo_patch);
Expand Down
27 changes: 27 additions & 0 deletions crates/bevy_reflect/src/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
Expand All @@ -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,
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 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>;
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
33 changes: 33 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,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:
Expand Down
27 changes: 27 additions & 0 deletions crates/bevy_reflect/src/tuple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
27 changes: 27 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,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:
Expand Down
17 changes: 4 additions & 13 deletions examples/reflection/dynamic_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand Down