pub(in crate::data::executor::handlers) const MIN_ROW_BYTES: usize = 16;
pub(in crate::data::executor::handlers) fn fetch_limit_for(
limit: usize,
offset: usize,
budget_bytes: usize,
) -> usize {
if limit == usize::MAX {
if budget_bytes == 0 {
return usize::MAX;
}
(budget_bytes / MIN_ROW_BYTES.max(1))
.saturating_add(1)
.max(1000)
} else {
(limit.saturating_add(offset)).saturating_mul(2).max(1000)
}
}
pub(in crate::data::executor::handlers) fn budget_exceeded(
total_bytes: usize,
budget_bytes: usize,
) -> bool {
budget_bytes != 0 && total_bytes > budget_bytes
}
pub(in crate::data::executor::handlers) fn scan_bytes_exceeded(
rows: &[(String, Vec<u8>)],
budget_bytes: usize,
) -> bool {
if budget_bytes == 0 {
return false;
}
let total = rows.iter().fold(0usize, |acc, (id, value)| {
acc.saturating_add(value.len()).saturating_add(id.len())
});
budget_exceeded(total, budget_bytes)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn explicit_limit_uses_heuristic() {
assert_eq!(fetch_limit_for(10, 5, 1024), 1000);
assert_eq!(fetch_limit_for(2000, 0, 1024), 4000);
}
#[test]
fn unbounded_limit_derives_from_budget() {
assert_eq!(fetch_limit_for(usize::MAX, 0, 1600), 1000);
assert_eq!(fetch_limit_for(usize::MAX, 0, 64 * 1024), 4097);
}
#[test]
fn unbounded_limit_does_not_overflow() {
let f = fetch_limit_for(usize::MAX, usize::MAX, usize::MAX);
assert!(f >= 1000);
}
#[test]
fn unbounded_limit_with_zero_budget_is_unlimited() {
assert_eq!(fetch_limit_for(usize::MAX, 0, 0), usize::MAX);
assert_eq!(fetch_limit_for(50, 0, 0), 1000);
}
#[test]
fn budget_of_zero_is_unlimited() {
assert!(!budget_exceeded(1_000_000, 0));
assert!(budget_exceeded(1025, 1024));
assert!(!budget_exceeded(1024, 1024));
}
#[test]
fn bytes_within_budget_not_exceeded() {
let rows = vec![
("a".to_string(), vec![0u8; 100]),
("b".to_string(), vec![0u8; 100]),
];
assert!(!scan_bytes_exceeded(&rows, 1024));
}
#[test]
fn bytes_over_budget_exceeded() {
let rows = vec![
("a".to_string(), vec![0u8; 600]),
("b".to_string(), vec![0u8; 600]),
];
assert!(scan_bytes_exceeded(&rows, 1024));
}
#[test]
fn zero_budget_disables_check() {
let rows = vec![("a".to_string(), vec![0u8; 1_000_000])];
assert!(!scan_bytes_exceeded(&rows, 0));
}
}