Skip to content

Commit 4343f2e

Browse files
soqbjames7132
authored andcommitted
reflect: add insert and remove methods to List (bevyengine#7063)
# Objective - Fixes bevyengine#7061 ## Solution - Add and implement `insert` and `remove` methods for `List`. --- ## Changelog - Added `insert` and `remove` methods to `List`. - Changed the `push` and `pop` methods on `List` to have default implementations. ## Migration Guide - Manual implementors of `List` need to implement the new methods `insert` and `remove` and consider whether to use the new default implementation of `push` and `pop`. Co-authored-by: radiish <[email protected]>
1 parent d823da0 commit 4343f2e

File tree

3 files changed

+73
-6
lines changed

3 files changed

+73
-6
lines changed

crates/bevy_reflect/src/impls/smallvec.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,22 @@ impl<T: smallvec::Array + Send + Sync + 'static> List for SmallVec<T>
4949
where
5050
T::Item: FromReflect,
5151
{
52+
fn insert(&mut self, index: usize, value: Box<dyn Reflect>) {
53+
let value = value.take::<T::Item>().unwrap_or_else(|value| {
54+
<T as smallvec::Array>::Item::from_reflect(&*value).unwrap_or_else(|| {
55+
panic!(
56+
"Attempted to insert invalid value of type {}.",
57+
value.type_name()
58+
)
59+
})
60+
});
61+
SmallVec::insert(self, index, value);
62+
}
63+
64+
fn remove(&mut self, index: usize) -> Box<dyn Reflect> {
65+
Box::new(self.remove(index))
66+
}
67+
5268
fn push(&mut self, value: Box<dyn Reflect>) {
5369
let value = value.take::<T::Item>().unwrap_or_else(|value| {
5470
<T as smallvec::Array>::Item::from_reflect(&*value).unwrap_or_else(|| {

crates/bevy_reflect/src/impls/std.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ impl_from_reflect_value!(NonZeroU8);
179179
impl_from_reflect_value!(NonZeroI8);
180180

181181
macro_rules! impl_reflect_for_veclike {
182-
($ty:ty, $push:expr, $pop:expr, $sub:ty) => {
182+
($ty:ty, $insert:expr, $remove:expr, $push:expr, $pop:expr, $sub:ty) => {
183183
impl<T: FromReflect> Array for $ty {
184184
#[inline]
185185
fn get(&self, index: usize) -> Option<&dyn Reflect> {
@@ -213,6 +213,22 @@ macro_rules! impl_reflect_for_veclike {
213213
}
214214

215215
impl<T: FromReflect> List for $ty {
216+
fn insert(&mut self, index: usize, value: Box<dyn Reflect>) {
217+
let value = value.take::<T>().unwrap_or_else(|value| {
218+
T::from_reflect(&*value).unwrap_or_else(|| {
219+
panic!(
220+
"Attempted to insert invalid value of type {}.",
221+
value.type_name()
222+
)
223+
})
224+
});
225+
$insert(self, index, value);
226+
}
227+
228+
fn remove(&mut self, index: usize) -> Box<dyn Reflect> {
229+
Box::new($remove(self, index))
230+
}
231+
216232
fn push(&mut self, value: Box<dyn Reflect>) {
217233
let value = value.take::<T>().unwrap_or_else(|value| {
218234
T::from_reflect(&*value).unwrap_or_else(|| {
@@ -328,9 +344,11 @@ macro_rules! impl_reflect_for_veclike {
328344
};
329345
}
330346

331-
impl_reflect_for_veclike!(Vec<T>, Vec::push, Vec::pop, [T]);
347+
impl_reflect_for_veclike!(Vec<T>, Vec::insert, Vec::remove, Vec::push, Vec::pop, [T]);
332348
impl_reflect_for_veclike!(
333349
VecDeque<T>,
350+
VecDeque::insert,
351+
VecDeque::remove,
334352
VecDeque::push_back,
335353
VecDeque::pop_back,
336354
VecDeque::<T>

crates/bevy_reflect/src/list.rs

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,43 @@ use crate::{
99

1010
/// An ordered, mutable list of [Reflect] items. This corresponds to types like [`std::vec::Vec`].
1111
///
12-
/// This is a sub-trait of [`Array`] as it implements a [`push`](List::push) function, allowing
13-
/// it's internal size to grow.
12+
/// This is a sub-trait of [`Array`], however as it implements [insertion](List::insert) and [removal](List::remove),
13+
/// it's internal size may change.
1414
///
1515
/// This trait expects index 0 to contain the _front_ element.
1616
/// The _back_ element must refer to the element with the largest index.
1717
/// These two rules above should be upheld by manual implementors.
18+
///
19+
/// [`push`](List::push) and [`pop`](List::pop) have default implementations,
20+
/// however it may be faster to implement them manually.
1821
pub trait List: Reflect + Array {
22+
/// Inserts an element at position `index` within the list,
23+
/// shifting all elements after it towards the back of the list.
24+
///
25+
/// # Panics
26+
/// Panics if `index > len`.
27+
fn insert(&mut self, index: usize, element: Box<dyn Reflect>);
28+
29+
/// Removes and returns the element at position `index` within the list,
30+
/// shifting all elements before it towards the front of the list.
31+
///
32+
/// # Panics
33+
/// Panics if `index` is out of bounds.
34+
fn remove(&mut self, index: usize) -> Box<dyn Reflect>;
35+
1936
/// Appends an element to the _back_ of the list.
20-
fn push(&mut self, value: Box<dyn Reflect>);
37+
fn push(&mut self, value: Box<dyn Reflect>) {
38+
self.insert(self.len(), value);
39+
}
2140

2241
/// Removes the _back_ element from the list and returns it, or [`None`] if it is empty.
23-
fn pop(&mut self) -> Option<Box<dyn Reflect>>;
42+
fn pop(&mut self) -> Option<Box<dyn Reflect>> {
43+
if self.is_empty() {
44+
None
45+
} else {
46+
Some(self.remove(self.len() - 1))
47+
}
48+
}
2449

2550
/// Clones the list, producing a [`DynamicList`].
2651
fn clone_dynamic(&self) -> DynamicList {
@@ -174,6 +199,14 @@ impl Array for DynamicList {
174199
}
175200

176201
impl List for DynamicList {
202+
fn insert(&mut self, index: usize, element: Box<dyn Reflect>) {
203+
self.values.insert(index, element);
204+
}
205+
206+
fn remove(&mut self, index: usize) -> Box<dyn Reflect> {
207+
self.values.remove(index)
208+
}
209+
177210
fn push(&mut self, value: Box<dyn Reflect>) {
178211
DynamicList::push_box(self, value);
179212
}

0 commit comments

Comments
 (0)