reflect: add insert and remove methods to List (#7063)
# Objective - Fixes #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 <thesethskigamer@gmail.com>
This commit is contained in:
parent
bef9bc1844
commit
1b9c156479
@ -49,6 +49,22 @@ impl<T: smallvec::Array + Send + Sync + 'static> List for SmallVec<T>
|
|||||||
where
|
where
|
||||||
T::Item: FromReflect,
|
T::Item: FromReflect,
|
||||||
{
|
{
|
||||||
|
fn insert(&mut self, index: usize, value: Box<dyn Reflect>) {
|
||||||
|
let value = value.take::<T::Item>().unwrap_or_else(|value| {
|
||||||
|
<T as smallvec::Array>::Item::from_reflect(&*value).unwrap_or_else(|| {
|
||||||
|
panic!(
|
||||||
|
"Attempted to insert invalid value of type {}.",
|
||||||
|
value.type_name()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
SmallVec::insert(self, index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove(&mut self, index: usize) -> Box<dyn Reflect> {
|
||||||
|
Box::new(self.remove(index))
|
||||||
|
}
|
||||||
|
|
||||||
fn push(&mut self, value: Box<dyn Reflect>) {
|
fn push(&mut self, value: Box<dyn Reflect>) {
|
||||||
let value = value.take::<T::Item>().unwrap_or_else(|value| {
|
let value = value.take::<T::Item>().unwrap_or_else(|value| {
|
||||||
<T as smallvec::Array>::Item::from_reflect(&*value).unwrap_or_else(|| {
|
<T as smallvec::Array>::Item::from_reflect(&*value).unwrap_or_else(|| {
|
||||||
|
|||||||
@ -179,7 +179,7 @@ impl_from_reflect_value!(NonZeroU8);
|
|||||||
impl_from_reflect_value!(NonZeroI8);
|
impl_from_reflect_value!(NonZeroI8);
|
||||||
|
|
||||||
macro_rules! impl_reflect_for_veclike {
|
macro_rules! impl_reflect_for_veclike {
|
||||||
($ty:ty, $push:expr, $pop:expr, $sub:ty) => {
|
($ty:ty, $insert:expr, $remove:expr, $push:expr, $pop:expr, $sub:ty) => {
|
||||||
impl<T: FromReflect> Array for $ty {
|
impl<T: FromReflect> Array for $ty {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get(&self, index: usize) -> Option<&dyn Reflect> {
|
fn get(&self, index: usize) -> Option<&dyn Reflect> {
|
||||||
@ -213,6 +213,22 @@ macro_rules! impl_reflect_for_veclike {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: FromReflect> List for $ty {
|
impl<T: FromReflect> List for $ty {
|
||||||
|
fn insert(&mut self, index: usize, value: Box<dyn Reflect>) {
|
||||||
|
let value = value.take::<T>().unwrap_or_else(|value| {
|
||||||
|
T::from_reflect(&*value).unwrap_or_else(|| {
|
||||||
|
panic!(
|
||||||
|
"Attempted to insert invalid value of type {}.",
|
||||||
|
value.type_name()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
$insert(self, index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove(&mut self, index: usize) -> Box<dyn Reflect> {
|
||||||
|
Box::new($remove(self, index))
|
||||||
|
}
|
||||||
|
|
||||||
fn push(&mut self, value: Box<dyn Reflect>) {
|
fn push(&mut self, value: Box<dyn Reflect>) {
|
||||||
let value = value.take::<T>().unwrap_or_else(|value| {
|
let value = value.take::<T>().unwrap_or_else(|value| {
|
||||||
T::from_reflect(&*value).unwrap_or_else(|| {
|
T::from_reflect(&*value).unwrap_or_else(|| {
|
||||||
@ -328,9 +344,11 @@ macro_rules! impl_reflect_for_veclike {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_reflect_for_veclike!(Vec<T>, Vec::push, Vec::pop, [T]);
|
impl_reflect_for_veclike!(Vec<T>, Vec::insert, Vec::remove, Vec::push, Vec::pop, [T]);
|
||||||
impl_reflect_for_veclike!(
|
impl_reflect_for_veclike!(
|
||||||
VecDeque<T>,
|
VecDeque<T>,
|
||||||
|
VecDeque::insert,
|
||||||
|
VecDeque::remove,
|
||||||
VecDeque::push_back,
|
VecDeque::push_back,
|
||||||
VecDeque::pop_back,
|
VecDeque::pop_back,
|
||||||
VecDeque::<T>
|
VecDeque::<T>
|
||||||
|
|||||||
@ -9,18 +9,43 @@ use crate::{
|
|||||||
|
|
||||||
/// An ordered, mutable list of [Reflect] items. This corresponds to types like [`std::vec::Vec`].
|
/// An ordered, mutable list of [Reflect] items. This corresponds to types like [`std::vec::Vec`].
|
||||||
///
|
///
|
||||||
/// This is a sub-trait of [`Array`] as it implements a [`push`](List::push) function, allowing
|
/// This is a sub-trait of [`Array`], however as it implements [insertion](List::insert) and [removal](List::remove),
|
||||||
/// it's internal size to grow.
|
/// it's internal size may change.
|
||||||
///
|
///
|
||||||
/// This trait expects index 0 to contain the _front_ element.
|
/// This trait expects index 0 to contain the _front_ element.
|
||||||
/// The _back_ element must refer to the element with the largest index.
|
/// The _back_ element must refer to the element with the largest index.
|
||||||
/// These two rules above should be upheld by manual implementors.
|
/// These two rules above should be upheld by manual implementors.
|
||||||
|
///
|
||||||
|
/// [`push`](List::push) and [`pop`](List::pop) have default implementations,
|
||||||
|
/// however it may be faster to implement them manually.
|
||||||
pub trait List: Reflect + Array {
|
pub trait List: Reflect + Array {
|
||||||
|
/// Inserts an element at position `index` within the list,
|
||||||
|
/// shifting all elements after it towards the back of the list.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
/// Panics if `index > len`.
|
||||||
|
fn insert(&mut self, index: usize, element: Box<dyn Reflect>);
|
||||||
|
|
||||||
|
/// Removes and returns the element at position `index` within the list,
|
||||||
|
/// shifting all elements before it towards the front of the list.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
/// Panics if `index` is out of bounds.
|
||||||
|
fn remove(&mut self, index: usize) -> Box<dyn Reflect>;
|
||||||
|
|
||||||
/// Appends an element to the _back_ of the list.
|
/// Appends an element to the _back_ of the list.
|
||||||
fn push(&mut self, value: Box<dyn Reflect>);
|
fn push(&mut self, value: Box<dyn Reflect>) {
|
||||||
|
self.insert(self.len(), value);
|
||||||
|
}
|
||||||
|
|
||||||
/// Removes the _back_ element from the list and returns it, or [`None`] if it is empty.
|
/// Removes the _back_ element from the list and returns it, or [`None`] if it is empty.
|
||||||
fn pop(&mut self) -> Option<Box<dyn Reflect>>;
|
fn pop(&mut self) -> Option<Box<dyn Reflect>> {
|
||||||
|
if self.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(self.remove(self.len() - 1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Clones the list, producing a [`DynamicList`].
|
/// Clones the list, producing a [`DynamicList`].
|
||||||
fn clone_dynamic(&self) -> DynamicList {
|
fn clone_dynamic(&self) -> DynamicList {
|
||||||
@ -174,6 +199,14 @@ impl Array for DynamicList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl List for DynamicList {
|
impl List for DynamicList {
|
||||||
|
fn insert(&mut self, index: usize, element: Box<dyn Reflect>) {
|
||||||
|
self.values.insert(index, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove(&mut self, index: usize) -> Box<dyn Reflect> {
|
||||||
|
self.values.remove(index)
|
||||||
|
}
|
||||||
|
|
||||||
fn push(&mut self, value: Box<dyn Reflect>) {
|
fn push(&mut self, value: Box<dyn Reflect>) {
|
||||||
DynamicList::push_box(self, value);
|
DynamicList::push_box(self, value);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user