use std::ptr; use std::slice; use crate::CapacityError; /// Implements basic arrayvec methods - based on a few required methods /// for length and element access. pub(crate) trait ArrayVecImpl { type Item; const CAPACITY: usize; fn len(&self) -> usize; unsafe fn set_len(&mut self, new_len: usize); /// Return a slice containing all elements of the vector. fn as_slice(&self) -> &[Self::Item] { let len = self.len(); unsafe { slice::from_raw_parts(self.as_ptr(), len) } } /// Return a mutable slice containing all elements of the vector. fn as_mut_slice(&mut self) -> &mut [Self::Item] { let len = self.len(); unsafe { std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) } } /// Return a raw pointer to the vector's buffer. fn as_ptr(&self) -> *const Self::Item; /// Return a raw mutable pointer to the vector's buffer. fn as_mut_ptr(&mut self) -> *mut Self::Item; #[track_caller] fn push(&mut self, element: Self::Item) { self.try_push(element).unwrap() } fn try_push(&mut self, element: Self::Item) -> Result<(), CapacityError> { if self.len() < Self::CAPACITY { unsafe { self.push_unchecked(element); } Ok(()) } else { Err(CapacityError::new(element)) } } unsafe fn push_unchecked(&mut self, element: Self::Item) { let len = self.len(); debug_assert!(len < Self::CAPACITY); ptr::write(self.as_mut_ptr().add(len), element); self.set_len(len + 1); } fn pop(&mut self) -> Option { if self.len() == 0 { return None; } unsafe { let new_len = self.len() - 1; self.set_len(new_len); Some(ptr::read(self.as_ptr().add(new_len))) } } fn clear(&mut self) { self.truncate(0) } fn truncate(&mut self, new_len: usize) { unsafe { let len = self.len(); if new_len < len { self.set_len(new_len); let tail = slice::from_raw_parts_mut(self.as_mut_ptr().add(new_len), len - new_len); ptr::drop_in_place(tail); } } } }