use alloc::string::String;
use spg_storage::{Row, Value};
use crate::EngineError;
pub(crate) fn approx_value_bytes(v: &Value) -> usize {
match v {
Value::Text(s) | Value::Json(s) => s.len(),
Value::Bytes(b) => b.len(),
Value::Vector(v) => v.len() * 4,
Value::TextArray(a) => a
.iter()
.map(|o| o.as_ref().map_or(0, String::len) + 8)
.sum(),
Value::IntArray(a) => a.len() * 8,
_ => 0,
}
}
pub(crate) fn approx_row_bytes(row: &Row) -> usize {
row.values.len() * core::mem::size_of::<Value>()
+ row.values.iter().map(approx_value_bytes).sum::<usize>()
}
pub(crate) struct ByteBudget {
limit: usize,
used: usize,
}
impl ByteBudget {
pub(crate) const fn new(limit: Option<usize>) -> Self {
Self {
limit: match limit {
Some(n) => n,
None => usize::MAX,
},
used: 0,
}
}
pub(crate) fn charge(&mut self, n: usize) -> Result<(), EngineError> {
self.used = self.used.saturating_add(n);
if self.used > self.limit {
return Err(EngineError::QueryBytesExceeded(self.limit));
}
Ok(())
}
pub(crate) fn release(&mut self, n: usize) {
self.used = self.used.saturating_sub(n);
}
}
pub(crate) fn approx_rows_bytes(rows: &[Row]) -> usize {
rows.iter().map(approx_row_bytes).sum()
}