diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index a7c1da4185b29..495f83d8cb5eb 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -30,6 +30,8 @@ pub trait Array: Reflect { } /// Returns an iterator over the collection. fn iter(&self) -> ArrayIter; + /// Drain the elements of this array to get a vector of owned values. + fn drain(self: Box) -> Vec>; fn clone_dynamic(&self) -> DynamicArray { DynamicArray { @@ -246,6 +248,11 @@ impl Array for DynamicArray { } } + #[inline] + fn drain(self: Box) -> Vec> { + self.values.into_vec() + } + #[inline] fn clone_dynamic(&self) -> DynamicArray { DynamicArray { diff --git a/crates/bevy_reflect/src/impls/smallvec.rs b/crates/bevy_reflect/src/impls/smallvec.rs index 11f3c80012110..ef855e9426379 100644 --- a/crates/bevy_reflect/src/impls/smallvec.rs +++ b/crates/bevy_reflect/src/impls/smallvec.rs @@ -37,6 +37,12 @@ where index: 0, } } + + fn drain(self: Box) -> Vec> { + self.into_iter() + .map(|value| Box::new(value) as Box) + .collect() + } } impl List for SmallVec diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 5c48fbabca74a..a99c2ef9987f4 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -123,6 +123,13 @@ impl Array for Vec { index: 0, } } + + #[inline] + fn drain(self: Box) -> Vec> { + self.into_iter() + .map(|value| Box::new(value) as Box) + .collect() + } } impl List for Vec { @@ -261,6 +268,17 @@ impl Map for HashMap { } } + fn drain(self: Box) -> Vec<(Box, Box)> { + self.into_iter() + .map(|(key, value)| { + ( + Box::new(key) as Box, + Box::new(value) as Box, + ) + }) + .collect() + } + fn clone_dynamic(&self) -> DynamicMap { let mut dynamic_map = DynamicMap::default(); dynamic_map.set_name(self.type_name().to_string()); @@ -409,6 +427,13 @@ impl Array for [T; N] { index: 0, } } + + #[inline] + fn drain(self: Box) -> Vec> { + self.into_iter() + .map(|value| Box::new(value) as Box) + .collect() + } } impl Reflect for [T; N] { diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index ef9e05ccd3cff..5f35d27e4e5a3 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -519,6 +519,29 @@ mod tests { assert_eq!(foo, *foo2.downcast::().unwrap()); } + #[test] + fn should_drain_fields() { + let array_value: Box = Box::new([123_i32, 321_i32]); + let fields = array_value.drain(); + assert!(fields[0].reflect_partial_eq(&123_i32).unwrap_or_default()); + assert!(fields[1].reflect_partial_eq(&321_i32).unwrap_or_default()); + + let list_value: Box = Box::new(vec![123_i32, 321_i32]); + let fields = list_value.drain(); + assert!(fields[0].reflect_partial_eq(&123_i32).unwrap_or_default()); + assert!(fields[1].reflect_partial_eq(&321_i32).unwrap_or_default()); + + let tuple_value: Box = Box::new((123_i32, 321_i32)); + let fields = tuple_value.drain(); + assert!(fields[0].reflect_partial_eq(&123_i32).unwrap_or_default()); + assert!(fields[1].reflect_partial_eq(&321_i32).unwrap_or_default()); + + let map_value: Box = Box::new(HashMap::from([(123_i32, 321_i32)])); + let fields = map_value.drain(); + assert!(fields[0].0.reflect_partial_eq(&123_i32).unwrap_or_default()); + assert!(fields[0].1.reflect_partial_eq(&321_i32).unwrap_or_default()); + } + #[test] fn reflect_take() { #[derive(Reflect, Debug, PartialEq)] diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index 26c8840c7f06f..b832e80c37e2a 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -137,6 +137,10 @@ impl Array for DynamicList { } } + fn drain(self: Box) -> Vec> { + self.values + } + fn clone_dynamic(&self) -> DynamicArray { DynamicArray { name: self.name.clone(), diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index 080b0770390b4..9bdeea87f61cb 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -42,6 +42,9 @@ pub trait Map: Reflect { /// Returns an iterator over the key-value pairs of the map. fn iter(&self) -> MapIter; + /// Drain the key-value pairs of this map to get a vector of owned values. + fn drain(self: Box) -> Vec<(Box, Box)>; + /// Clones the map, producing a [`DynamicMap`]. fn clone_dynamic(&self) -> DynamicMap; @@ -226,6 +229,10 @@ impl Map for DynamicMap { } } } + + fn drain(self: Box) -> Vec<(Box, Box)> { + self.values + } } impl Reflect for DynamicMap { diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index 96386e85d6bbc..13469c0be3fcb 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -40,6 +40,9 @@ pub trait Tuple: Reflect { /// Returns an iterator over the values of the tuple's fields. fn iter_fields(&self) -> TupleFieldIter; + /// Drain the fields of this tuple to get a vector of owned values. + fn drain(self: Box) -> Vec>; + /// Clones the struct into a [`DynamicTuple`]. fn clone_dynamic(&self) -> DynamicTuple; } @@ -253,6 +256,11 @@ impl Tuple for DynamicTuple { } } + #[inline] + fn drain(self: Box) -> Vec> { + self.fields + } + #[inline] fn clone_dynamic(&self) -> DynamicTuple { DynamicTuple { @@ -451,6 +459,13 @@ macro_rules! impl_reflect_tuple { } } + #[inline] + fn drain(self: Box) -> Vec> { + vec![ + $(Box::new(self.$index),)* + ] + } + #[inline] fn clone_dynamic(&self) -> DynamicTuple { let mut dyn_tuple = DynamicTuple {