#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ReserveStrategy {
Exact,
Grow50,
Double,
PowerOfTwo,
}
#[must_use]
pub fn reserve_capacity(needed: usize, strategy: ReserveStrategy) -> usize {
match strategy {
ReserveStrategy::Exact => needed,
ReserveStrategy::Grow50 => needed + needed / 2,
ReserveStrategy::Double => needed * 2,
ReserveStrategy::PowerOfTwo => needed.next_power_of_two(),
}
}
#[derive(Debug)]
pub struct StrategicBuffer {
data: Vec<u8>,
strategy: ReserveStrategy,
}
impl StrategicBuffer {
pub fn new(strategy: ReserveStrategy) -> Self {
Self { data: Vec::new(), strategy }
}
pub fn with_capacity(capacity: usize, strategy: ReserveStrategy) -> Self {
Self { data: Vec::with_capacity(reserve_capacity(capacity, strategy)), strategy }
}
pub fn reserve(&mut self, additional: usize) {
let needed = self.data.len() + additional;
if needed > self.data.capacity() {
let new_cap = reserve_capacity(needed, self.strategy);
self.data.reserve(new_cap - self.data.capacity());
}
}
pub fn write(&mut self, bytes: &[u8]) {
contract_pre_write!();
self.reserve(bytes.len());
self.data.extend_from_slice(bytes);
}
#[must_use]
pub fn as_slice(&self) -> &[u8] {
&self.data
}
#[must_use]
pub fn len(&self) -> usize {
self.data.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
#[must_use]
pub fn capacity(&self) -> usize {
self.data.capacity()
}
pub fn clear(&mut self) {
self.data.clear();
}
}
impl Default for StrategicBuffer {
fn default() -> Self {
Self::new(ReserveStrategy::Double)
}
}