#[derive(Debug, Clone, Hash, Default, PartialEq, Eq)]
pub struct NonEmptyVec<T> {
first: T,
others: Vec<T>,
}
impl<T> NonEmptyVec<T> {
#[inline]
pub fn new(first: T) -> Self {
NonEmptyVec {
first,
others: Vec::new(),
}
}
#[inline]
pub fn with_capacity(first: T, other_capacity: usize) -> Self {
NonEmptyVec {
first,
others: Vec::with_capacity(other_capacity),
}
}
#[inline]
pub fn first(&self) -> &T {
&self.first
}
#[inline]
pub fn last(&self) -> &T {
self.others.last().unwrap_or(&self.first)
}
#[inline]
pub fn others(&self) -> &[T] {
&self.others
}
#[inline]
pub fn len(&self) -> usize {
self.others.len() + 1
}
#[inline]
pub fn is_single(&self) -> bool {
self.others.is_empty()
}
#[inline]
pub fn first_mut(&mut self) -> &mut T {
&mut self.first
}
#[inline]
pub fn last_mut(&mut self) -> &mut T {
self.others.last_mut().unwrap_or(&mut self.first)
}
#[inline]
pub fn others_mut(&mut self) -> &mut Vec<T> {
&mut self.others
}
#[inline]
pub fn push(&mut self, item: T) {
self.others.push(item);
}
#[inline]
pub fn pop(&mut self) -> Option<T> {
self.others.pop()
}
}
impl<T> From<NonEmptyVec<T>> for (T, Vec<T>) {
#[inline]
fn from(vec: NonEmptyVec<T>) -> (T, Vec<T>) {
let NonEmptyVec { first, others } = vec;
(first, others)
}
}
impl<T> From<NonEmptyVec<T>> for Vec<T> {
#[inline]
fn from(vec: NonEmptyVec<T>) -> Vec<T> {
let NonEmptyVec { first, mut others } = vec;
others.insert(0, first);
others
}
}
#[test]
fn first() {
macro_rules! check {
($vec:expr, $values:expr $(,)?) => {{
assert_eq!(
$vec.first(),
&$values[0],
"First value doesn't match expected",
);
assert_eq!(
$vec.others(),
&$values[1..],
"Remaining values don't match expected",
);
}};
}
let mut vec = NonEmptyVec::new(0);
check!(vec, [0]);
vec.push(1);
check!(vec, [0, 1]);
vec.push(2);
check!(vec, [0, 1, 2]);
assert_eq!(vec.pop(), Some(2));
check!(vec, [0, 1]);
}
#[test]
fn others() {
let mut vec = NonEmptyVec::with_capacity('a', 2);
vec.push('b');
vec.others_mut().push('c');
*vec.first_mut() = 'z';
{
let (first, others) = vec.clone().into();
assert_eq!(first, 'z', "First value doesn't match expected");
assert_eq!(
others,
vec!['b', 'c'],
"Remaining values don't match expected",
);
}
{
let items: Vec<char> = vec.clone().into();
assert_eq!(
items,
vec!['z', 'b', 'c'],
"Remaining values don't match expected",
);
}
}