mod drop;
use local_vec::LocalVec;
pub enum SmallVec<T, const N: usize> {
LocalBuf(LocalVec<T, N>),
RemoteBuf(Vec<T>),
}
use SmallVec::*;
impl<T, const N: usize> SmallVec<T, N> {
pub fn new() -> Self {
LocalBuf(LocalVec::new())
}
pub fn len(&self) -> usize {
match self {
LocalBuf(vec) => vec.len(),
RemoteBuf(vec) => vec.len(),
}
}
pub fn is_local(&self) -> bool {
match self {
LocalBuf(_) => true,
RemoteBuf(_) => false,
}
}
pub fn is_remote(&self) -> bool {
return !self.is_local()
}
pub fn push(&mut self, val: T) {
match self {
LocalBuf(local_vec) => {
if !local_vec.is_full() {
local_vec.push(val);
} else {
let cap = {
local_vec.len()
.checked_add(1)
.expect("new capacity would overflow capacity type")
};
let mut vec = Vec::with_capacity(cap);
let arr = local_vec.take_array();
vec.extend(arr);
vec.push(val);
*self = RemoteBuf(vec);
}
},
RemoteBuf(vec) => {
vec.push(val);
},
}
}
pub fn pop(&mut self) -> Option<T> {
match self {
LocalBuf(vec) => vec.pop(),
RemoteBuf(vec) => vec.pop(),
}
}
}
#[cfg(test)]
mod tests {
use crate::SmallVec;
#[test]
fn test_new() {
SmallVec::<u8, 32>::new();
}
#[test]
fn test_zero_len() {
let buf = SmallVec::<u8, 32>::new();
assert_eq!(buf.len(), 0);
}
#[test]
fn test_switch_from_local_to_remote() {
let mut buf = SmallVec::<usize, 4>::new();
assert_eq!(buf.len(), 0);
buf.push(1);
assert_eq!(buf.len(), 1);
assert!(buf.is_local());
buf.push(2);
assert_eq!(buf.len(), 2);
assert!(buf.is_local());
buf.push(3);
assert_eq!(buf.len(), 3);
assert!(buf.is_local());
buf.push(4);
assert_eq!(buf.len(), 4);
assert!(buf.is_local());
buf.push(5);
assert_eq!(buf.len(), 5);
assert!(buf.is_remote());
buf.push(6);
assert_eq!(buf.len(), 6);
assert!(buf.is_remote());
}
#[test]
fn test_push_and_pop_locally() {
let mut buf = SmallVec::<_, 4>::new();
buf.push(1usize);
buf.push(2);
buf.push(3);
buf.push(4);
assert!(buf.is_local());
assert_eq!(buf.pop(), Some(4));
assert_eq!(buf.pop(), Some(3));
assert_eq!(buf.pop(), Some(2));
assert_eq!(buf.pop(), Some(1));
assert_eq!(buf.pop(), None);
assert_eq!(buf.pop(), None);
}
#[test]
fn test_push_and_pop_remotely() {
let mut buf = SmallVec::<_, 4>::new();
buf.push(1usize);
buf.push(2);
buf.push(3);
buf.push(4);
assert_eq!(buf.len(), 4);
assert!(buf.is_local());
buf.push(5);
assert_eq!(buf.len(), 5);
assert!(buf.is_remote());
buf.push(6);
buf.push(7);
assert_eq!(buf.len(), 7);
assert_eq!(buf.pop(), Some(7));
assert_eq!(buf.pop(), Some(6));
assert_eq!(buf.pop(), Some(5));
assert_eq!(buf.pop(), Some(4));
assert_eq!(buf.pop(), Some(3));
assert_eq!(buf.pop(), Some(2));
assert_eq!(buf.pop(), Some(1));
assert_eq!(buf.pop(), None);
assert_eq!(buf.pop(), None);
}
}