#[allow(dead_code)]
fn f64_to_usize_saturating(x: f64) -> usize {
x.max(0.0).min(usize::MAX as f64) as usize
}
pub fn estimate_tokens(text: &str, chars_per_token: f64) -> usize {
let count = text.chars().count();
if count == 0 {
return 0;
}
let cpt = if chars_per_token > 0.0 && chars_per_token.is_finite() {
chars_per_token
} else {
1.0
};
f64_to_usize_saturating((count as f64 / cpt).ceil())
}
#[allow(dead_code)]
pub fn budget_after_margin(budget: usize, headroom: usize, margin_ratio: f64) -> usize {
let margin = if margin_ratio > 0.0 && margin_ratio.is_finite() {
((budget as f64 * margin_ratio).ceil() as usize).min(budget)
} else {
0
};
budget.saturating_sub(headroom).saturating_sub(margin)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_token_estimate_is_conservative_and_margin_reserves_headroom() {
assert_eq!(estimate_tokens("abcdefg", 3.5), 2); assert_eq!(estimate_tokens("", 3.5), 0);
assert_eq!(budget_after_margin(8000, 1024, 0.1), 8000 - 1024 - 800);
}
#[test]
fn test_budget_after_margin_saturates_to_zero() {
assert_eq!(budget_after_margin(100, 1024, 0.1), 0); }
#[test]
fn test_estimate_counts_unicode_scalars_and_handles_bad_cpt() {
assert_eq!(estimate_tokens("héllo", 1.0), 5); assert_eq!(estimate_tokens("abc", 0.0), 3); }
#[test]
fn test_budget_holds_with_cjk_chars_per_token() {
assert!(estimate_tokens("你好世界", 2.0) >= estimate_tokens("你好世界", 3.5));
}
#[test]
fn test_f64_to_usize_saturating_handles_extreme_inputs() {
assert_eq!(f64_to_usize_saturating(f64::NAN), 0, "NaN must map to 0");
assert_eq!(
f64_to_usize_saturating(f64::INFINITY),
usize::MAX,
"+Inf must saturate to usize::MAX"
);
assert_eq!(
f64_to_usize_saturating(1e300),
usize::MAX,
"huge finite must saturate to usize::MAX"
);
assert_eq!(f64_to_usize_saturating(-42.0), 0, "negative must map to 0");
assert_eq!(
f64_to_usize_saturating(7.0),
7,
"normal value must round-trip"
);
}
#[test]
fn test_budget_after_margin_does_not_panic_on_max_budget() {
let result = budget_after_margin(usize::MAX, 0, 0.5);
assert!(
result < usize::MAX,
"J2: result must be less than usize::MAX (margin was reserved)"
);
assert!(result > 0, "J2: result must be positive with a 50% margin");
}
}