Skip to main content

amethystate_core/primitives/
intercept.rs

1use std::sync::Arc;
2use std::sync::atomic::{AtomicUsize, Ordering};
3
4pub(crate) const MAX_INTERCEPT_DEPTH: usize = 10;
5
6pub struct InterceptGuard {
7    depth: Arc<AtomicUsize>,
8}
9
10impl InterceptGuard {
11    pub(crate) fn enter(depth: &Arc<AtomicUsize>, path: Arc<str>) -> Option<Self> {
12        let prev = depth.fetch_add(1, Ordering::Acquire);
13        if prev >= MAX_INTERCEPT_DEPTH {
14            depth.fetch_sub(1, Ordering::Release);
15            tracing::warn!(
16                target: "amethystate::intercept",
17                path = %path,
18                depth = prev + 1,
19                "maximum intercept depth reached, skipping execution"
20            );
21            None
22        } else {
23            Some(Self {
24                depth: depth.clone(),
25            })
26        }
27    }
28}
29
30impl Drop for InterceptGuard {
31    fn drop(&mut self) {
32        self.depth.fetch_sub(1, Ordering::Release);
33    }
34}
35
36pub struct InterceptDisposer {
37    pub id: u64,
38    pub path: Arc<str>,
39    pub(crate) cleanup: Arc<dyn Fn(u64) + Send + Sync + 'static>,
40}
41
42impl InterceptDisposer {
43    pub fn remove(self) {
44        (self.cleanup)(self.id);
45    }
46}
47
48impl std::fmt::Debug for InterceptDisposer {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        f.debug_struct("InterceptDisposer")
51            .field("id", &self.id)
52            .field("path", &self.path)
53            .finish()
54    }
55}