#![no_std]
use core::borrow::{Borrow, BorrowMut};
use core::ops::{Deref, DerefMut};
use core::mem::{swap, replace};
use core::cmp;
#[derive(Debug)]
pub struct SliceVec<'a, T: 'a> {
storage: &'a mut [T],
len: usize,
}
impl<'a, T> SliceVec<'a, T> {
pub fn new(storage: &'a mut [T]) -> Self {
SliceVec {
storage: storage,
len: 0,
}
}
pub fn capacity(&self) -> usize {
self.storage.len()
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn is_full(&self) -> bool {
self.len == self.storage.len()
}
pub fn push(&mut self, elem: T) -> Result<(), T> {
if self.len < self.capacity() {
self.storage[self.len] = elem;
self.len += 1;
Ok(())
} else {
Err(elem)
}
}
pub fn pop_and_replace(&mut self, elem: T) -> Option<T> {
if self.len > 0 {
self.len -= 1;
let elem = replace(&mut self.storage[self.len], elem);
Some(elem)
} else {
None
}
}
pub fn truncate(&mut self, len: usize) {
self.len = cmp::min(self.len, len);
}
pub fn clear(&mut self) {
self.truncate(0);
}
pub fn as_slice(&self) -> &[T] {
&self.storage[..self.len]
}
pub fn as_mut_slice(&mut self) -> &mut [T] {
&mut self.storage[..self.len]
}
}
impl<'a, T: 'a + Default> SliceVec<'a, T> {
pub fn pop(&mut self) -> Option<T> {
if self.len > 0 {
self.len -= 1;
let elem = replace(&mut self.storage[self.len], T::default());
Some(elem)
} else {
None
}
}
pub fn swap_remove(&mut self, index: usize) -> T {
let len = self.len();
self.as_mut_slice().swap(index, len - 1);
self.pop().expect("swap_remove failed pop")
}
pub fn remove(&mut self, index: usize) -> T {
assert!(index < self.len);
let mut replacement = T::default();
for i in (index..self.len).rev() {
swap(&mut self.storage[i], &mut replacement);
}
self.len -= 1;
replacement
}
}
impl<'a, T> Deref for SliceVec<'a, T> {
type Target = [T];
fn deref(&self) -> &[T] {
self.as_slice()
}
}
impl<'a, T> DerefMut for SliceVec<'a, T> {
fn deref_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
impl<'a, T> AsRef<[T]> for SliceVec<'a, T> {
fn as_ref(&self) -> &[T] {
self.as_slice()
}
}
impl<'a, T> AsMut<[T]> for SliceVec<'a, T> {
fn as_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
impl<'a, T> Borrow<[T]> for SliceVec<'a, T> {
fn borrow(&self) -> &[T] {
self.as_slice()
}
}
impl<'a, T> BorrowMut<[T]> for SliceVec<'a, T> {
fn borrow_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn basic() {
const CAP: usize = 1;
let mut storage = [0; CAP];
{
let mut s = SliceVec::new(&mut storage);
assert!(s.is_empty());
assert_eq!(s.len(), 0);
assert_eq!(s.capacity(), CAP);
assert_eq!(s.push(123), Ok(()));
assert_eq!(s.len(), 1);
assert!(!s.is_empty());
assert_eq!(s.as_slice(), &[123]);
assert_eq!(s.push(42), Err(42));
assert!(!s.is_empty());
assert_eq!(s.as_slice(), &[123]);
assert_eq!(s.pop(), Some(123));
assert_eq!(s.len(), 0);
assert!(s.is_empty());
assert_eq!(s.as_slice(), &[]);
assert_eq!(&*s, &[]);
}
}
#[test]
fn swap_remove() {
let mut storage = [0; 5];
let mut v = SliceVec::new(&mut storage);
v.push(0).unwrap();
v.push(1).unwrap();
v.push(2).unwrap();
v.push(3).unwrap();
assert_eq!(v.as_slice(), &[0, 1, 2, 3]);
assert_eq!(v.swap_remove(0), 0);
assert_eq!(v.as_slice(), &[3, 1, 2]);
assert_eq!(v.swap_remove(2), 2);
assert_eq!(v.as_slice(), &[3, 1]);
v.push(100).unwrap();
v.push(101).unwrap();
assert_eq!(v.as_slice(), &[3, 1, 100, 101]);
assert_eq!(v.swap_remove(2), 100);
assert_eq!(v.as_slice(), &[3, 1, 101]);
v.push(102).unwrap();
assert_eq!(v.as_slice(), &[3, 1, 101, 102]);
assert_eq!(v.swap_remove(1), 1);
assert_eq!(v.as_slice(), &[3, 102, 101]);
}
#[test]
#[should_panic]
fn swap_remove_empty() {
let mut storage = [0; 5];
let mut v = SliceVec::new(&mut storage);
v.push(7).unwrap();
v.clear();
assert_eq!(v.as_slice(), &[]);
assert!(v.is_empty());
v.swap_remove(0);
}
#[test]
#[should_panic]
fn swap_remove_out_of_bounds() {
let mut storage = [0; 5];
let mut v = SliceVec::new(&mut storage);
v.push(0).unwrap();
v.push(1).unwrap();
v.push(2).unwrap();
v.push(3).unwrap();
assert_eq!(v.as_slice(), &[0, 1, 2, 3]);
v.swap_remove(4);
}
#[test]
fn remove() {
let mut storage = [0; 5];
let mut v = SliceVec::new(&mut storage);
v.push(0).unwrap();
v.push(1).unwrap();
v.push(2).unwrap();
v.push(3).unwrap();
assert_eq!(v.remove(0), 0);
assert_eq!(v.as_slice(), &[1, 2, 3]);
assert_eq!(v.remove(2), 3);
assert_eq!(v.as_slice(), &[1, 2]);
v.push(3).unwrap();
v.push(4).unwrap();
v.push(5).unwrap();
assert_eq!(v.as_slice(), &[1, 2, 3, 4, 5]);
assert_eq!(v.remove(1), 2);
assert_eq!(v.as_slice(), &[1, 3, 4, 5]);
}
#[test]
#[should_panic]
fn remove_empty() {
let mut storage = [0; 5];
let mut v = SliceVec::new(&mut storage);
v.push(7).unwrap();
v.clear();
assert_eq!(v.as_slice(), &[]);
assert!(v.is_empty());
v.remove(0);
}
#[test]
#[should_panic]
fn remove_out_of_bounds() {
let mut storage = [0; 5];
let mut v = SliceVec::new(&mut storage);
v.push(0).unwrap();
v.push(1).unwrap();
v.push(2).unwrap();
v.push(3).unwrap();
assert_eq!(v.as_slice(), &[0, 1, 2, 3]);
v.remove(4);
}
#[test]
fn is_full() {
let mut storage = [0; 3];
let mut v = SliceVec::new(&mut storage);
assert!(!v.is_full());
v.push(0).unwrap();
assert!(!v.is_full());
v.push(1).unwrap();
assert!(!v.is_full());
v.push(2).unwrap();
assert!(v.is_full());
v.push(3).unwrap_err();
}
}