mod encoding;
mod expr;
mod predicate;
#[cfg(test)]
mod tests;
mod text;
mod value;
use crate::error::InternalError;
use icydb_diagnostic_code::DiagnosticExecutionBudgetResource as Resource;
pub(in crate::db) use encoding::{ENCODING_NODE_BYTES, encoded_value_capacity};
pub(in crate::db) trait ConstructionBudget {
fn charge(&self, resource: Resource, amount: u64) -> Result<(), InternalError>;
fn admit_format_scratch(&self, bytes: u64, steps: u64) -> Result<(), InternalError> {
self.charge(Resource::TemporaryBytes, bytes)?;
self.charge(Resource::PredicateExpressionSteps, steps)
}
}
impl dyn ConstructionBudget + '_ {
pub(in crate::db) fn copy_slice<T, U>(
&self,
values: &[T],
mut copy: impl FnMut(&T) -> Result<U, InternalError>,
) -> Result<Vec<U>, InternalError> {
let mut out = self.vec_with_capacity(values.len())?;
for value in values {
out.push(copy(value)?);
}
Ok(out)
}
pub(in crate::db) fn copy_text(&self, text: &str) -> Result<String, InternalError> {
self.charge(Resource::PredicateExpressionSteps, 1 + text.len() as u64)?;
self.charge(Resource::TemporaryBytes, text.len() as u64)?;
Ok(text.to_string())
}
pub(in crate::db) fn vec_with_capacity<T>(&self, len: usize) -> Result<Vec<T>, InternalError> {
self.charge(
Resource::TemporaryBytes,
(len as u64).saturating_mul(size_of::<T>() as u64),
)?;
Ok(Vec::with_capacity(len))
}
pub(in crate::db) fn boxed<T>(&self, value: T) -> Result<Box<T>, InternalError> {
self.charge(Resource::TemporaryBytes, size_of::<T>() as u64)?;
Ok(Box::new(value))
}
pub(in crate::db) fn reserve_vec<T>(
&self,
values: &mut Vec<T>,
additional: usize,
) -> Result<(), InternalError> {
let capacity =
self.reserve_capacity(values.len(), values.capacity(), additional, size_of::<T>())?;
if capacity > values.capacity() {
values.reserve_exact(capacity - values.len());
}
Ok(())
}
pub(in crate::db) fn reserve_string(
&self,
text: &mut String,
additional: usize,
) -> Result<(), InternalError> {
let capacity = self.reserve_capacity(text.len(), text.capacity(), additional, 1)?;
if capacity > text.capacity() {
text.reserve_exact(capacity - text.len());
}
Ok(())
}
fn reserve_capacity(
&self,
len: usize,
capacity: usize,
additional: usize,
element_bytes: usize,
) -> Result<usize, InternalError> {
let required = len
.checked_add(additional)
.ok_or_else(InternalError::query_executor_invariant)?;
if required <= capacity {
return Ok(capacity);
}
let next = required.max(capacity.saturating_mul(2)).max(4);
self.charge(
Resource::TemporaryBytes,
(next as u64).saturating_mul(element_bytes as u64),
)?;
Ok(next)
}
pub(in crate::db) fn push_text(
&self,
out: &mut String,
text: &str,
) -> Result<(), InternalError> {
self.charge(Resource::PredicateExpressionSteps, text.len() as u64)?;
self.reserve_string(out, text.len())?;
out.push_str(text);
Ok(())
}
}