use std::any::TypeId; use super::{Reflect, util}; pub trait List: Reflect { fn get(&self, idx: usize) -> Option<&dyn Reflect>; fn get_mut(&mut self, idx: usize) -> Option<&mut dyn Reflect>; /// Push a value to the end of the List. If `item` is not the same type of the list, /// it will be returned as [`Result::Err`]. fn push_back(&mut self, item: Box) -> Result<(), Box>; fn push_front(&mut self, item: Box) -> Result<(), Box>; /// Removes an item at `idx` from the List and returns the owned value. fn remove_at(&mut self, idx: usize) -> Option>; /// Removes the last element from the vector and returns it, `None` if it is empty. fn pop_back(&mut self) -> Option>; /// Removes the first element from the vector and returns it, `None` if it is empty. /// /// Keep in mind this is slow if the List is not a `VecDeque`, or some other list type that is /// optimized for removing from the front. fn pop_front(&mut self) -> Option>; /// Append a list to this list, removing the elements from `other`. fn append(&mut self, other: &mut dyn List); /// Reserves at least `additional` more space in the List. The spaces are not /// initialized to anything. fn reserve(&mut self, additional: usize); /// Returns the length of the list fn len(&self) -> usize; /// Returns the total number of elements the list can hold without reallocating. fn capacity(&self) -> usize; /// Returns a boolean indicating if the list is empty. fn is_empty(&self) -> bool; /// Returns the TypeId of the elements in the list fn elements_id(&self) -> TypeId; fn apply_list(&mut self, other: &dyn List); /// Creates a new, and empty list of the same type. fn create_empty(&self) -> Box; } impl List for Vec { fn get(&self, idx: usize) -> Option<&dyn Reflect> { if idx < self.len() { Some(&self[idx]) } else { None } } fn get_mut(&mut self, idx: usize) -> Option<&mut dyn Reflect> { if idx < self.len() { Some(&mut self[idx]) } else { None } } fn push_back(&mut self, item: Box) -> Result<(), Box> { if item.is(TypeId::of::()) { let item = *(item as Box).downcast::() .unwrap(); self.push(item); Ok(()) } else { Err(item) } } fn push_front(&mut self, _item: Box) -> Result<(), Box> { unimplemented!("push_front for `List` trait implementation of a `Vec`. Doing so is slow!") } fn remove_at(&mut self, idx: usize) -> Option> { if idx < self.len() { let removed = Box::new(self.remove(idx)); Some(removed) } else { None } } fn pop_back(&mut self) -> Option> { let popped = Box::new(self.pop()); Some(popped) } fn pop_front(&mut self) -> Option> { unimplemented!("pop_front for `List` trait implementation of a `Vec`. Doing so is slow!") } fn append(&mut self, other: &mut dyn List) { assert!(self.elements_id() == other.elements_id(), "Provided a List that contains elements that don't match what's in Self!"); self.reserve(other.len()); // pop_back and reverse later is probably the best to use here. I don't have iterators // written for `List` yet, and an implementation of pop_front for a `Vec` would be slow. let mut other_elements = vec![]; while let Some(el) = other.pop_back() { let el = *(el as Box).downcast::() .expect("msg"); other_elements.push(el); } other_elements.reverse(); self.append(&mut other_elements); } fn len(&self) -> usize { self.len() } fn is_empty(&self) -> bool { self.is_empty() } fn elements_id(&self) -> TypeId { TypeId::of::() } fn apply_list(&mut self, other: &dyn List) { util::apply_list(self, other); } fn create_empty(&self) -> Box { Box::new(Vec::::new()) } fn reserve(&mut self, additional: usize) { self.reserve(additional); } fn capacity(&self) -> usize { self.capacity() } }