#![crate_type = "lib"]
#![crate_name = "fixedvec"]
#![no_std]
use core::hash::{Hash, Hasher};
use core::ops;
#[cfg(test)]
#[macro_use]
extern crate std;
#[macro_export]
macro_rules! alloc_stack {
([$item_type:ty; $len:expr]) => {{
let space: [$item_type; $len] = [Default::default(); $len];
space
}};
}
pub type Result<T> = core::result::Result<T, ErrorKind>;
#[derive(Debug)]
pub enum ErrorKind {
NoSpace,
}
#[derive(Debug)]
pub struct FixedVec<'a, T: 'a + Copy> {
memory: &'a mut [T],
len: usize,
}
pub use core::slice::Iter;
pub use core::slice::IterMut;
impl<'a, T> FixedVec<'a, T>
where
T: 'a + Copy,
{
pub fn new(memory: &'a mut [T]) -> Self {
FixedVec {
memory: memory,
len: 0,
}
}
#[inline]
pub fn capacity(&self) -> usize {
self.memory.len()
}
#[inline]
pub fn len(&self) -> usize {
self.len
}
#[inline]
pub fn available(&self) -> usize {
self.capacity() - self.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
pub fn as_slice(&self) -> &[T] {
&self.memory[..self.len]
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [T] {
&mut self.memory[..self.len]
}
pub fn insert(&mut self, index: usize, element: T) -> Result<()> {
assert!(index <= self.len);
if index == self.len || self.len == 0 {
self.push(element)
} else if self.available() >= 1 {
self.len += 1;
let mut i = self.len;
loop {
if i == index {
break;
}
self.memory[i] = self.memory[i - 1];
i -= 1;
}
self.memory[index] = element;
Ok(())
} else {
Err(ErrorKind::NoSpace)
}
}
pub fn remove(&mut self, index: usize) -> T {
assert!(index < self.len);
let ret = self.memory[index];
self.len -= 1;
for i in index..self.len {
self.memory[i] = self.memory[i + 1];
}
ret
}
#[inline]
pub fn push(&mut self, value: T) -> Result<()> {
if self.available() >= 1 {
self.memory[self.len] = value;
self.len += 1;
Ok(())
} else {
Err(ErrorKind::NoSpace)
}
}
#[inline]
pub fn pop(&mut self) -> Option<T> {
if self.len > 0 {
self.len -= 1;
Some(self.memory[self.len])
} else {
None
}
}
#[inline]
pub fn push_all(&mut self, other: &[T]) -> Result<()> {
if other.len() > self.available() {
Err(ErrorKind::NoSpace)
} else {
for item in other.iter() {
self.memory[self.len] = *item;
self.len += 1;
}
Ok(())
}
}
pub fn clear(&mut self) {
self.len = 0
}
pub fn map_in_place<F>(&mut self, f: F)
where
F: Fn(&mut T),
{
for i in 0..self.len {
f(&mut self.memory[i]);
}
}
#[inline]
pub fn iter(&self) -> Iter<T> {
let (slice, _) = self.memory.split_at(self.len);
slice.iter()
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<T> {
let (slice, _) = self.memory.split_at_mut(self.len);
slice.iter_mut()
}
pub fn swap_remove(&mut self, index: usize) -> T {
assert!(index < self.len);
if self.len == 1 {
self.remove(0)
} else {
let removed = self.memory[index];
self.memory[index] = self.pop().unwrap();
removed
}
}
pub fn resize(&mut self, new_len: usize, value: T) {
assert!(new_len <= self.capacity());
if new_len <= self.len {
self.len = new_len;
} else {
for i in self.memory[self.len..new_len].iter_mut() {
*i = Clone::clone(&value);
}
self.len = new_len;
}
}
pub fn retain<F>(&mut self, f: F)
where
F: Fn(&T) -> bool,
{
let mut head: usize = 0;
let mut tail: usize = 0;
loop {
if head >= self.len {
break;
}
if f(&self.memory[head]) {
self.memory[tail] = self.memory[head];
tail += 1;
}
head += 1;
}
self.len = tail;
}
pub fn get(&self, index: usize) -> Option<&T> {
self.as_slice().get(index)
}
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
self.as_mut_slice().get_mut(index)
}
pub unsafe fn get_unchecked(&self, index: usize) -> &T {
self.as_slice().get_unchecked(index)
}
pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
self.as_mut_slice().get_unchecked_mut(index)
}
}
impl<'a, T> FixedVec<'a, T>
where
T: 'a + Copy + PartialEq<T>,
{
pub fn dedup(&mut self) {
if self.len <= 1 {
return;
}
let mut head: usize = 1;
let mut tail: usize = 0;
loop {
if head >= self.len {
break;
}
if self.memory[head] != self.memory[tail] {
tail += 1;
self.memory[tail] = self.memory[head];
}
head += 1;
}
self.len = tail + 1;
}
}
impl<'a, T: Copy> IntoIterator for &'a FixedVec<'a, T> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Iter<'a, T> {
self.iter()
}
}
impl<'a, T: Copy> IntoIterator for &'a mut FixedVec<'a, T> {
type Item = &'a mut T;
type IntoIter = IterMut<'a, T>;
fn into_iter(self) -> IterMut<'a, T> {
self.iter_mut()
}
}
impl<'a, T> Hash for FixedVec<'a, T>
where
T: Copy + Hash,
{
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
Hash::hash(&*self.memory, state)
}
}
impl<'a, T> Extend<T> for FixedVec<'a, T>
where
T: Copy,
{
fn extend<I: IntoIterator<Item = T>>(&mut self, iterable: I) {
if self.available() == 0 {
return;
}
for n in iterable {
self.memory[self.len] = n;
self.len += 1;
if self.available() == 0 {
break;
}
}
}
}
impl<'a, T> ops::Index<usize> for FixedVec<'a, T>
where
T: Copy,
{
type Output = T;
#[inline]
fn index(&self, index: usize) -> &T {
&(self.memory)[index]
}
}
impl<'a, T> ops::IndexMut<usize> for FixedVec<'a, T>
where
T: Copy,
{
#[inline]
fn index_mut(&mut self, index: usize) -> &mut T {
&mut (self.memory)[index]
}
}
impl<'a, T> PartialEq for FixedVec<'a, T>
where
T: Copy + PartialEq,
{
fn eq(&self, other: &FixedVec<'a, T>) -> bool {
if self.len() != other.len() {
return false;
}
(0..self.len()).all(|i| self[i] == other[i])
}
}
impl<'a, T> Eq for FixedVec<'a, T> where T: Copy + Eq {}
#[cfg(test)]
mod test {
use super::FixedVec;
use std::collections::hash_map::DefaultHasher;
use std::hash::Hash;
use std::prelude::v1::*;
#[test]
fn test_empty_array() {
let mut empty = alloc_stack!([u8; 0]);
let mut vec = FixedVec::new(&mut empty);
assert!(vec.is_empty());
assert_eq!(vec.capacity(), 0);
assert_eq!(vec.len(), 0);
assert_eq!(vec.available(), 0);
assert_eq!(vec.as_slice(), &[] as &[u8]);
assert!(vec.push(0).is_err());
assert!(vec.push_all(&[] as &[u8]).is_ok());
assert!(vec.push_all(&[1]).is_err());
vec.clear();
vec.map_in_place(|x: &mut u8| *x = 1);
vec.retain(|_: &u8| true);
vec.dedup();
{
let mut iter = vec.iter();
assert!(iter.next().is_none());
}
}
#[test]
#[should_panic]
fn test_insert_bad_index() {
let mut space = alloc_stack!([u8; 10]);
let mut vec = FixedVec::new(&mut space);
vec.insert(3, 0).unwrap();
}
#[test]
#[should_panic]
fn test_remove_bad_index() {
let mut space = alloc_stack!([u8; 10]);
let mut vec = FixedVec::new(&mut space);
vec.push_all(&[1, 2, 3, 4, 5]).unwrap();
vec.remove(8);
}
#[test]
#[should_panic]
fn test_resize_bad_len() {
let mut space = alloc_stack!([u8; 10]);
let mut vec = FixedVec::new(&mut space);
vec.resize(15, 0);
}
#[test]
#[should_panic]
fn test_swap_remove_bad_index() {
let mut space = alloc_stack!([u8; 10]);
let mut vec = FixedVec::new(&mut space);
vec.push_all(&[1, 2, 3, 4, 5]).unwrap();
vec.swap_remove(8);
}
#[test]
fn test_iterator() {
let mut space = alloc_stack!([u8; 10]);
let mut vec = FixedVec::new(&mut space);
vec.push_all(&[1, 2, 3, 4, 5]).unwrap();
let result: Vec<u8> = vec.iter().map(|&x| x).collect();
assert_eq!(vec.as_slice(), &result[..]);
}
#[test]
fn test_hash() {
let mut space1 = alloc_stack!([u8; 10]);
let mut vec1 = FixedVec::new(&mut space1);
let mut hasher1 = DefaultHasher::new();
vec1.push_all(&[1, 2, 3, 4, 5]).unwrap();
let mut space2 = alloc_stack!([u8; 10]);
let mut vec2 = FixedVec::new(&mut space2);
let mut hasher2 = DefaultHasher::new();
vec2.push_all(&[1, 2, 3, 4, 5]).unwrap();
assert_eq!(vec1.hash(&mut hasher1), vec2.hash(&mut hasher2));
}
#[test]
fn test_extend() {
let mut space = alloc_stack!([u8; 10]);
let mut vec = FixedVec::new(&mut space);
vec.extend(0..6);
assert_eq!(vec.as_slice(), &[0, 1, 2, 3, 4, 5]);
}
#[test]
fn test_equal() {
let mut space1 = alloc_stack!([u8; 10]);
let mut vec1 = FixedVec::new(&mut space1);
vec1.push_all(&[1, 2, 3, 4, 5]).unwrap();
let mut space2 = alloc_stack!([u8; 5]);
let mut vec2 = FixedVec::new(&mut space2);
vec2.push_all(&[1, 2, 3, 4, 5]).unwrap();
assert_eq!(vec1, vec2);
}
}