extern crate alloc;
use crate::error::ExprError;
#[cfg(not(test))]
use alloc::format;
#[cfg(not(test))]
use core::sync::atomic::{AtomicUsize, Ordering};
#[cfg(test)]
use std::sync::atomic::{AtomicUsize, Ordering};
pub static RECURSION_DEPTH: AtomicUsize = AtomicUsize::new(0);
#[cfg(test)]
const MAX_RECURSION_DEPTH: usize = 10; #[cfg(not(test))]
const MAX_RECURSION_DEPTH: usize = 100;
pub fn check_and_increment_recursion_depth() -> Result<(), ExprError> {
let current = RECURSION_DEPTH.load(Ordering::Relaxed);
if current > MAX_RECURSION_DEPTH - 10 && current < MAX_RECURSION_DEPTH {
#[cfg(test)]
eprintln!(
"WARNING: Unusually high recursion depth detected: {}",
current
);
}
if current >= MAX_RECURSION_DEPTH {
RECURSION_DEPTH.store(0, Ordering::Relaxed);
Err(ExprError::RecursionLimit(format!(
"Maximum recursion depth of {} exceeded during expression evaluation",
MAX_RECURSION_DEPTH
)))
} else {
RECURSION_DEPTH.store(current + 1, Ordering::Relaxed);
Ok(())
}
}
pub fn decrement_recursion_depth() {
let current = RECURSION_DEPTH.load(Ordering::Relaxed);
if current > 0 {
RECURSION_DEPTH.store(current - 1, Ordering::Relaxed);
}
}
pub fn get_recursion_depth() -> usize {
RECURSION_DEPTH.load(Ordering::Relaxed)
}
pub fn reset_recursion_depth() {
RECURSION_DEPTH.store(0, Ordering::Relaxed)
}
pub fn set_max_recursion_depth(depth: usize) -> usize {
depth
}