pub trait MemoryEstimator: Send + Sync {
fn estimate_bytes(&self, items_buffered: usize) -> usize;
fn name(&self) -> &'static str;
}
#[derive(Debug, Clone)]
pub struct ConservativeEstimator;
impl MemoryEstimator for ConservativeEstimator {
fn estimate_bytes(&self, items_buffered: usize) -> usize {
items_buffered * 2048 }
fn name(&self) -> &'static str {
"conservative_2kb"
}
}
#[derive(Debug, Clone)]
pub struct FixedEstimator {
bytes_per_item: usize,
}
impl FixedEstimator {
pub const fn new(bytes_per_item: usize) -> Self {
Self { bytes_per_item }
}
}
impl MemoryEstimator for FixedEstimator {
fn estimate_bytes(&self, items_buffered: usize) -> usize {
items_buffered.saturating_mul(self.bytes_per_item)
}
fn name(&self) -> &'static str {
"fixed_custom"
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_conservative_estimator() {
let est = ConservativeEstimator;
assert_eq!(est.estimate_bytes(0), 0);
assert_eq!(est.estimate_bytes(1), 2048);
assert_eq!(est.estimate_bytes(100), 204_800);
assert_eq!(est.estimate_bytes(256), 524_288);
}
#[test]
fn test_conservative_name() {
let est = ConservativeEstimator;
assert_eq!(est.name(), "conservative_2kb");
}
#[test]
fn test_fixed_estimator() {
let est = FixedEstimator::new(4096);
assert_eq!(est.estimate_bytes(0), 0);
assert_eq!(est.estimate_bytes(1), 4096);
assert_eq!(est.estimate_bytes(100), 409_600);
assert_eq!(est.estimate_bytes(256), 1_048_576);
}
#[test]
fn test_fixed_estimator_custom_sizes() {
for size in &[1024, 2048, 4096, 8192] {
let est = FixedEstimator::new(*size);
assert_eq!(est.estimate_bytes(10), 10 * size);
}
}
#[test]
fn test_fixed_estimator_overflow_safe() {
let est = FixedEstimator::new(usize::MAX / 2);
let _ = est.estimate_bytes(usize::MAX);
}
}