use super::errors::*;
use std::mem::swap;
pub enum StorageUnit<T: 'static> {
Nope,
One(T),
Many(Vec<T>),
}
impl<T: Sized> StorageUnit<T> {
#[inline(always)]
pub fn new() -> Self {
StorageUnit::Nope
}
pub fn insert(&mut self, new: T) {
match self {
StorageUnit::Nope => {
*self = StorageUnit::One(new);
}
StorageUnit::One(_) => {
let mut rep = StorageUnit::Many(vec![new]);
swap(self, &mut rep);
if let StorageUnit::One(prev) = rep {
if let StorageUnit::Many(v) = self {
v.insert(0, prev);
} else {
unreachable!()
}
} else {
unreachable!()
}
}
StorageUnit::Many(many) => {
many.push(new);
}
}
}
pub fn insert_many(&mut self, mut new: Vec<T>) {
match self {
StorageUnit::Nope => {
*self = StorageUnit::Many(new);
}
StorageUnit::One(_) => {
let mut rep = StorageUnit::Many(new);
swap(&mut rep, self);
if let StorageUnit::One(val) = rep {
if let StorageUnit::Many(vec) = self {
vec.insert(0, val);
} else {
unreachable!()
}
} else {
unreachable!()
}
}
StorageUnit::Many(arr) => {
arr.append(&mut new);
}
}
}
#[inline]
pub fn one(&self) -> DynamicResult<&T> {
if let StorageUnit::One(x) = self {
Ok(x)
} else {
Err(ErrorDesc::Unit(UnitError::IsNotOne))
}
}
#[inline]
pub fn one_mut(&mut self) -> DynamicResult<&mut T> {
if let StorageUnit::One(x) = self {
Ok(x)
} else {
Err(ErrorDesc::Unit(UnitError::IsNotOne))
}
}
#[inline]
pub fn many(&self) -> DynamicResult<&[T]> {
if let StorageUnit::Many(x) = self {
Ok(x)
} else {
Err(ErrorDesc::Unit(UnitError::IsNotMany))
}
}
#[inline]
pub fn many_mut(&mut self) -> DynamicResult<&mut Vec<T>> {
if let StorageUnit::Many(x) = self {
Ok(x)
} else {
Err(ErrorDesc::Unit(UnitError::IsNotMany))
}
}
pub fn extract_one(&mut self) -> DynamicResult<T> {
match self {
StorageUnit::Nope => Err(ErrorDesc::Unit(UnitError::IsNotOne)),
StorageUnit::Many(x) => Ok(x.remove(0)),
StorageUnit::One(_) => {
let mut repl = StorageUnit::Nope;
swap(&mut repl, self);
if let StorageUnit::One(data) = repl {
Ok(data)
} else {
unreachable!()
}
}
}
}
pub fn extract_many(&mut self) -> DynamicResult<Vec<T>> {
match self {
StorageUnit::Nope => Err(ErrorDesc::Unit(UnitError::IsNotMany)),
StorageUnit::One(_) => {
let mut repl = StorageUnit::Nope;
swap(&mut repl, self);
if let StorageUnit::One(data) = repl {
Ok(vec![data])
} else {
unreachable!()
}
}
StorageUnit::Many(_) => {
let mut repl = StorageUnit::Nope;
swap(&mut repl, self);
if let StorageUnit::Many(data) = repl {
Ok(data)
} else {
unreachable!()
}
}
}
}
pub fn extract_many_boxed(&mut self) -> DynamicResult<Box<[T]>> {
match self {
StorageUnit::Nope => Err(ErrorDesc::Unit(UnitError::IsNotMany)),
StorageUnit::One(_) => Err(ErrorDesc::Unit(UnitError::IsNotMany)),
StorageUnit::Many(_) => {
let mut repl = StorageUnit::Nope;
swap(&mut repl, self);
if let StorageUnit::Many(data) = repl {
Ok(data.into_boxed_slice())
} else {
unreachable!()
}
}
}
}
#[inline]
pub fn rearrange_if_necessary(&mut self) {
if let StorageUnit::Many(v) = self {
match v.as_slice() {
[] => *self = StorageUnit::Nope,
[_] => {
let mut one_container = StorageUnit::Nope;
swap(self, &mut one_container);
if let StorageUnit::Many(mut v) = one_container {
*self = StorageUnit::One(v.remove(0));
} else {
unreachable!()
}
}
_ => {}
}
}
}
}
impl<T> Default for StorageUnit<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: Clone> Clone for StorageUnit<T> {
fn clone(&self) -> Self {
match self {
StorageUnit::Nope => StorageUnit::Nope,
StorageUnit::One(data) => StorageUnit::One(data.clone()),
StorageUnit::Many(data) => StorageUnit::Many(data.clone()),
}
}
}