pub struct GrowableBuffer<T: Clone> {
buf: Vec<Option<T>>,
}
impl<T: Clone> GrowableBuffer<T> {
pub fn new(size_hint: usize) -> Self {
Self {
buf: vec![None; size_hint],
}
}
fn grow(&mut self, access_idx: usize) {
let new_size = usize::max(access_idx + 1, self.buf.len() * 2);
self.buf.resize(new_size, None);
}
pub fn get(&self, idx: usize) -> Option<&T> {
if idx >= self.buf.len() {
return None;
}
self.buf[idx].as_ref()
}
pub fn get_mut(&mut self, idx: usize) -> Option<&mut T> {
if idx >= self.buf.len() {
self.grow(idx)
}
self.buf[idx].as_mut()
}
pub fn entry_mut(&mut self, idx: usize) -> &mut Option<T> {
if idx >= self.buf.len() {
self.grow(idx)
}
&mut self.buf[idx]
}
pub fn insert(&mut self, idx: usize, val: T) -> Option<T> {
if idx >= self.buf.len() {
self.grow(idx)
}
self.buf.get_mut(idx).unwrap().replace(val)
}
pub fn take(&mut self, idx: usize) -> Option<T> {
let val = self.buf.get_mut(idx)?;
val.take()
}
}
#[cfg(test)]
mod test {
use super::GrowableBuffer;
#[test]
fn test_empty_buf() {
let mut buf = GrowableBuffer::new(10);
assert_eq!(buf.get(1), None);
buf.insert(1, 1);
assert_eq!(buf.get(1), Some(&1));
}
#[test]
fn test_grow_buf() {
let mut buf: GrowableBuffer<u64> = GrowableBuffer::new(2);
assert_eq!(buf.get(2), None);
buf.insert(2, 2);
assert_eq!(buf.get(2), Some(&2));
}
#[test]
fn test_mutable_entry() {
let mut buf: GrowableBuffer<u64> = GrowableBuffer::new(2);
buf.insert(2, 2);
*buf.get_mut(2).unwrap() += 1;
assert_eq!(buf.get(2), Some(&3));
}
#[test]
fn test_entry() {
let mut buf: GrowableBuffer<Vec<u64>> = GrowableBuffer::new(2);
let entry = buf.entry_mut(0).get_or_insert(vec![]);
entry.push(1);
assert_eq!(buf.get(0), Some(&vec![1]));
}
#[test]
fn test_take() {
let mut buf: GrowableBuffer<u64> = GrowableBuffer::new(2);
buf.insert(2, 2);
assert_eq!(buf.take(2), Some(2));
assert_eq!(buf.get(2), None);
}
}