use std::ops::Index;
#[derive(Debug, Default, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Nevec<T> {
first: T,
tail: Vec<T>,
}
impl<T> Nevec<T> {
pub fn new(first: T) -> Nevec<T> {
Nevec::<T>::new_with_tail(first, Vec::new())
}
pub fn with_capacity(first: T, capacity: usize) -> Nevec<T> {
Nevec::<T>::new_with_tail(first, Vec::with_capacity(capacity))
}
pub fn new_with_tail(first: T, tail: Vec<T>) -> Nevec<T> {
Nevec { first, tail }
}
pub fn last(&self) -> &T {
match self.tail.last() {
None => &self.first,
Some(t) => t,
}
}
pub fn last_mut(&mut self) -> &mut T {
match self.tail.last_mut() {
None => &mut self.first,
Some(t) => t,
}
}
pub fn push(&mut self, t: T) {
self.tail.push(t)
}
pub fn pop(mut self) -> T {
match self.tail.pop() {
None => self.first,
Some(t) => t,
}
}
pub fn pop_from_tail(&mut self) -> Option<T> {
self.tail.pop()
}
pub fn len(&self) -> usize {
1 + self.tail.len()
}
pub fn is_empty(&self) -> bool {
true
}
pub fn get(&self, i: usize) -> Option<&T> {
if i == 0 {
return Some(&self.first);
}
self.tail.get(i - 1)
}
pub fn get_mut(&mut self, i: usize) -> Option<&mut T> {
if i == 0 {
return Some(&mut self.first);
}
self.tail.get_mut(i - 1)
}
}
impl<T> Index<usize> for Nevec<T> {
type Output = T;
fn index(&self, i: usize) -> &Self::Output {
if i == 0 {
&self.first
} else {
&self.tail[i - 1]
}
}
}
impl<'a, T> IntoIterator for &'a Nevec<T> {
type Item = &'a T;
type IntoIter = NevecIter<'a, T>;
fn into_iter(self) -> NevecIter<'a, T> {
NevecIter { vec: self, i: 0 }
}
}
impl<T: std::fmt::Display> std::fmt::Display for Nevec<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for t in self {
write![f, "{t}"]?;
}
Ok(())
}
}
pub struct NevecIter<'a, T> {
vec: &'a Nevec<T>,
i: usize,
}
impl<'a, T> Iterator for NevecIter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
if self.i >= self.vec.len() {
None
} else {
self.i += 1;
Some(&self.vec[self.i - 1])
}
}
}
#[macro_export]
macro_rules! nevec {
( $first: expr, $ ( $ x : expr ) , * ) => (
Nevec::new_with_tail($first, vec![$ ( $ x ) , *])
);
( $first: expr, $ ( $ x : expr , ) * ) => ( nevec ! [ $first, $ ( $ x ) , * ] );
( $first: expr ) => {
Nevec::new($first)
};
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn singleton_vector() {
let mut v = nevec![3];
assert_eq![v.len(), 1];
assert_eq![v.last(), &3];
assert_eq![v.last_mut(), &3];
assert_eq![v.pop_from_tail(), None];
assert_eq![v.pop(), 3];
}
#[test]
fn two_element_vector() {
let mut v = nevec![3, 4];
assert_eq![v.len(), 2];
assert_eq![v.last(), &4];
assert_eq![v.last_mut(), &4];
assert_eq![v[0], 3];
assert_eq![v[1], 4];
assert_eq![v.pop_from_tail(), Some(4)];
assert_eq![v.last(), &3];
assert_eq![v.last_mut(), &3];
assert_eq![v.pop_from_tail(), None];
}
#[test]
fn vector_with_push() {
let mut v = nevec![3, 4,];
assert_eq![v.len(), 2];
v.push(5);
assert_eq![v.len(), 3];
assert_eq![v.last(), &5];
assert_eq![v.last_mut(), &5];
assert_eq![v.pop_from_tail(), Some(5)];
}
#[test]
fn other_macro_constructor_case() {
let mut v = nevec![3,];
assert_eq![v.len(), 1];
assert_eq![v.last(), &3];
assert_eq![v.last_mut(), &3];
assert_eq![v.pop_from_tail(), None];
assert_eq![v.pop(), 3];
}
}