use proc_macro2::Span;
use crate::core::types::{ParseResult, err};
const MAX_RECURSION_DEPTH: u32 = 128;
thread_local! {
static RECURSION_DEPTH: std::cell::Cell<u32> = std::cell::Cell::new(0);
}
pub struct RecursionGuard;
impl RecursionGuard {
pub fn new() -> Result<Self, ParseResult> {
let mut reached_limit = false;
RECURSION_DEPTH.with(|depth| {
let d = depth.get();
if d >= MAX_RECURSION_DEPTH {
reached_limit = true;
} else {
depth.set(d + 1);
}
});
if reached_limit {
Err(ParseResult::Err(err(
Span::call_site(),
&format!("递归深度超过上限 {},可能存在过深的嵌套", MAX_RECURSION_DEPTH),
)))
} else {
Ok(RecursionGuard)
}
}
}
impl Drop for RecursionGuard {
fn drop(&mut self) {
RECURSION_DEPTH.with(|depth| {
depth.set(depth.get() - 1);
});
}
}
pub fn span_suffix(span: Span) -> u64 {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let mut hasher = DefaultHasher::new();
span.byte_range().hash(&mut hasher);
hasher.finish()
}