use smallvec::{Array, SmallVec};
use super::{reconcile_buffer_capacity, replacement, MemoryBudget, MemoryError, MemoryReservation};
pub struct BudgetedSmallVec<A: Array> {
values: SmallVec<A>,
memory: MemoryReservation,
}
impl<A: Array> BudgetedSmallVec<A> {
pub fn new(budget: &MemoryBudget) -> Self {
Self {
values: SmallVec::new(),
memory: budget.empty_reservation(),
}
}
pub fn capacity(&self) -> usize {
self.values.capacity()
}
pub fn spilled(&self) -> bool {
self.values.spilled()
}
pub fn budget(&self) -> &MemoryBudget {
self.memory.budget()
}
pub fn reserve(&mut self, additional: usize) -> Result<(), MemoryError> {
let required = self
.values
.len()
.checked_add(additional)
.ok_or(MemoryError::SizeOverflow)?;
if required <= self.values.capacity() {
return Ok(());
}
let heap = if self.values.spilled() {
self.values.capacity()
} else {
0
};
let (capacity, mut memory) = replacement::<A::Item>(self.memory.budget(), heap, required)?;
let mut buffer = Vec::new();
buffer.try_reserve_exact(capacity)?;
reconcile_buffer_capacity::<A::Item>(&mut memory, buffer.capacity())?;
buffer.extend(self.values.drain(..));
self.values = SmallVec::from_vec(buffer);
self.memory = memory;
Ok(())
}
pub fn push(&mut self, value: A::Item) -> Result<(), MemoryError> {
self.reserve(1)?;
self.values.push(value);
Ok(())
}
pub fn pop(&mut self) -> Option<A::Item> {
self.values.pop()
}
pub fn clear(&mut self) {
self.values.clear();
}
pub fn truncate(&mut self, len: usize) {
self.values.truncate(len);
}
}
impl<A: Array> std::ops::Deref for BudgetedSmallVec<A> {
type Target = [A::Item];
fn deref(&self) -> &[A::Item] {
&self.values
}
}
impl<A: Array> std::ops::DerefMut for BudgetedSmallVec<A> {
fn deref_mut(&mut self) -> &mut [A::Item] {
&mut self.values
}
}
impl<A: Array> std::fmt::Debug for BudgetedSmallVec<A>
where
A::Item: std::fmt::Debug,
{
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter
.debug_struct("BudgetedSmallVec")
.field("values", &&*self.values)
.field("memory", &self.memory)
.finish()
}
}
#[cfg(test)]
mod tests;