use crate::seg_list::SegList;
use core::fmt;
pub struct Various<T> {
inner: VariousInner<T>,
}
enum VariousInner<T> {
One(Option<T>),
More(SegList<T>),
}
impl<T> Default for Various<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> Various<T> {
#[inline]
pub fn new() -> Self {
Self { inner: VariousInner::One(None) }
}
#[inline]
pub fn from(item: T) -> Self {
Self { inner: VariousInner::One(Some(item)) }
}
#[inline]
pub fn is_empty(&self) -> bool {
match &self.inner {
VariousInner::One(i) => i.is_none(),
VariousInner::More(i) => i.is_empty(),
}
}
#[inline]
pub fn len(&self) -> usize {
match &self.inner {
VariousInner::One(i) => {
if i.is_none() {
0
} else {
1
}
}
VariousInner::More(i) => i.len(),
}
}
#[inline]
pub fn push(&mut self, new_item: T) {
match self.inner {
VariousInner::More(ref mut s) => {
s.push(new_item);
}
VariousInner::One(ref mut s) => {
if s.is_none() {
s.replace(new_item);
} else {
let mut l = SegList::new();
l.push(s.take().unwrap());
l.push(new_item);
self.inner = VariousInner::More(l);
}
}
}
}
#[inline]
pub fn pop(&mut self) -> Option<T> {
match self.inner {
VariousInner::More(ref mut s) => s.pop(),
VariousInner::One(ref mut s) => s.take(),
}
}
#[inline]
pub fn iter(&self) -> VariousIter<'_, T> {
let inner = match &self.inner {
VariousInner::One(s) => VariousIterInner::One(s.iter()),
VariousInner::More(s) => VariousIterInner::More(s.iter()),
};
VariousIter { inner }
}
pub fn iter_mut(&mut self) -> VariousIterMut<'_, T> {
let inner = match &mut self.inner {
VariousInner::One(s) => VariousIterMutInner::One(s.iter_mut()),
VariousInner::More(s) => VariousIterMutInner::More(s.iter_mut()),
};
VariousIterMut { inner }
}
#[inline]
pub fn first(&self) -> Option<&T> {
match self.inner {
VariousInner::One(ref s) => s.as_ref(),
VariousInner::More(ref s) => s.iter().next(),
}
}
#[inline]
pub fn last(&self) -> Option<&T> {
match self.inner {
VariousInner::More(ref s) => s.last(),
VariousInner::One(ref s) => s.as_ref(),
}
}
pub fn last_mut(&mut self) -> Option<&mut T> {
match self.inner {
VariousInner::More(ref mut s) => s.last_mut(),
VariousInner::One(ref mut s) => s.as_mut(),
}
}
#[inline]
pub fn iter_rev(&self) -> VariousIter<'_, T> {
let inner = match &self.inner {
VariousInner::One(s) => VariousIterInner::One(s.iter()),
VariousInner::More(s) => VariousIterInner::More(s.iter_rev()),
};
VariousIter { inner }
}
#[inline]
pub fn iter_mut_rev(&mut self) -> VariousIterMut<'_, T> {
let inner = match &mut self.inner {
VariousInner::One(s) => VariousIterMutInner::One(s.iter_mut()),
VariousInner::More(s) => VariousIterMutInner::More(s.iter_mut_rev()),
};
VariousIterMut { inner }
}
#[inline]
pub fn take(&mut self) -> Self {
use core::mem;
Various { inner: mem::replace(&mut self.inner, VariousInner::One(None)) }
}
#[inline]
pub fn clear(&mut self) {
match &mut self.inner {
VariousInner::One(inner) => {
let _ = inner.take();
}
VariousInner::More(inner) => inner.clear(),
}
}
}
impl<T> IntoIterator for Various<T> {
type Item = T;
type IntoIter = VariousIntoIter<T>;
fn into_iter(self) -> VariousIntoIter<T> {
let inner = match self.inner {
VariousInner::One(s) => VariousIntoIterInner::One(s.into_iter()),
VariousInner::More(s) => VariousIntoIterInner::More(s.drain()),
};
VariousIntoIter { inner }
}
}
impl<T> Various<T> {
#[inline]
pub fn into_rev(self) -> VariousIntoIter<T> {
let inner = match self.inner {
VariousInner::One(s) => VariousIntoIterInner::One(s.into_iter()),
VariousInner::More(s) => VariousIntoIterInner::More(s.into_rev()),
};
VariousIntoIter { inner }
}
}
impl<'a, T> IntoIterator for &'a Various<T> {
type Item = &'a T;
type IntoIter = VariousIter<'a, T>;
fn into_iter(self) -> VariousIter<'a, T> {
self.iter()
}
}
pub struct VariousIter<'a, T> {
inner: VariousIterInner<'a, T>,
}
enum VariousIterInner<'a, T> {
One(core::option::Iter<'a, T>),
More(crate::seg_list::SegListIter<'a, T>),
}
impl<'a, T> core::iter::Iterator for VariousIter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
match &mut self.inner {
VariousIterInner::One(i) => i.next(),
VariousIterInner::More(i) => i.next(),
}
}
}
pub struct VariousIterMut<'a, T> {
inner: VariousIterMutInner<'a, T>,
}
enum VariousIterMutInner<'a, T> {
One(core::option::IterMut<'a, T>),
More(crate::seg_list::SegListIterMut<'a, T>),
}
impl<'a, T> core::iter::Iterator for VariousIterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
match &mut self.inner {
VariousIterMutInner::One(i) => i.next(),
VariousIterMutInner::More(i) => i.next(),
}
}
}
pub struct VariousIntoIter<T> {
inner: VariousIntoIterInner<T>,
}
enum VariousIntoIterInner<T> {
One(core::option::IntoIter<T>),
More(crate::seg_list::SegListDrain<T>),
}
impl<T> core::iter::Iterator for VariousIntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
match &mut self.inner {
VariousIntoIterInner::One(i) => i.next(),
VariousIntoIterInner::More(i) => i.next(),
}
}
}
impl<T: fmt::Debug> fmt::Debug for Various<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self.inner {
VariousInner::One(s) => s.fmt(f),
VariousInner::More(s) => s.fmt(f),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_one() {
let mut s = Various::new();
s.push(1);
assert_eq!(s.len(), 1);
for i in &s {
assert_eq!(*i, 1);
}
assert_eq!(Some(1), s.pop());
assert_eq!(s.len(), 0);
if (&s).into_iter().next().is_some() {
unreachable!();
}
}
#[test]
fn test_cap_0() {
let mut s = Various::new();
s.push(1);
assert_eq!(s.len(), 1);
for i in &s {
assert_eq!(*i, 1);
}
s.push(2);
s.push(3);
assert_eq!(s.len(), 3);
let mut total = 0;
for i in &s {
total += *i;
}
assert_eq!(total, 6);
for i in s.iter_mut() {
*i += 1;
}
let mut total = 0;
for i in &s {
total += *i;
}
assert_eq!(total, 9);
assert_eq!(s.pop(), Some(4));
let mut total = 0;
for i in s {
total += i;
}
assert_eq!(total, 5);
}
#[test]
fn test_more() {
let mut s = Various::new();
s.push(1);
s.push(2);
s.push(3);
assert_eq!(s.len(), 3);
let mut total = 0;
for i in &s {
total += *i;
}
assert_eq!(total, 6);
for i in s.iter_mut() {
*i += 1;
}
let mut total = 0;
for i in &s {
total += *i;
}
assert_eq!(total, 9);
assert_eq!(s.pop(), Some(4));
let mut total = 0;
for i in s {
total += i;
}
assert_eq!(total, 5);
}
#[test]
fn test_iter_rev_one() {
let mut s = Various::new();
s.push(42);
let collected: Vec<i32> = s.iter_rev().copied().collect();
assert_eq!(collected, vec![42]);
for i in s.iter_mut_rev() {
*i *= 10;
}
assert_eq!(s.first(), Some(&420));
}
#[test]
fn test_iter_rev_more() {
let mut s = Various::new();
s.push(1);
s.push(2);
s.push(3);
let collected: Vec<i32> = s.iter_rev().copied().collect();
assert_eq!(collected, vec![3, 2, 1]);
for i in s.iter_mut_rev() {
*i *= 10;
}
let collected: Vec<i32> = s.iter().copied().collect();
assert_eq!(collected, vec![10, 20, 30]);
}
#[test]
fn test_iter_rev_empty() {
let s: Various<i32> = Various::new();
let collected: Vec<i32> = s.iter_rev().copied().collect();
assert!(collected.is_empty());
let mut s_mut: Various<i32> = Various::new();
let count = s_mut.iter_mut_rev().count();
assert_eq!(count, 0);
}
#[test]
fn test_into_rev_one() {
let mut s = Various::new();
s.push(42);
let collected: Vec<i32> = s.into_rev().collect();
assert_eq!(collected, vec![42]);
}
#[test]
fn test_into_rev_more() {
let mut s = Various::new();
s.push(1);
s.push(2);
s.push(3);
let collected: Vec<i32> = s.into_rev().collect();
assert_eq!(collected, vec![3, 2, 1]);
}
#[test]
fn test_into_rev_empty() {
let s: Various<i32> = Various::new();
let collected: Vec<i32> = s.into_rev().collect();
assert!(collected.is_empty());
}
}