amethystate_core/primitives/
intercept.rs1use 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}