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
	 radiish
						radiish