rapiddoc_core/
resources.rs1use std::{cell::Cell, marker::PhantomData, rc::Rc};
7
8thread_local! { static COMPATIBLE: Cell<bool> = const { Cell::new(false) }; }
9
10pub struct Scope {
11 previous: bool,
12 _thread: PhantomData<Rc<()>>,
13}
14
15pub fn python_compatible() -> Scope {
16 Scope {
17 previous: COMPATIBLE.with(|v| v.replace(true)),
18 _thread: PhantomData,
19 }
20}
21
22#[inline]
23pub fn is_python_compatible() -> bool {
24 COMPATIBLE.with(Cell::get)
25}
26
27impl Drop for Scope {
28 fn drop(&mut self) {
29 COMPATIBLE.with(|v| v.set(self.previous));
30 }
31}
32
33pub trait Bound: Copy + Default + PartialEq {
34 const REPRESENTABLE_MAX: Self;
35}
36macro_rules! bounds {
37 ($($t:ty),*) => {$ (impl Bound for $t { const REPRESENTABLE_MAX: Self = <$t>::MAX; })*};
38}
39bounds!(usize, u32, u64, i32, i64, f32, f64);
40
41#[inline]
44pub fn limit<T: Bound>(diagnostic: T) -> T {
45 if COMPATIBLE.with(Cell::get) && diagnostic != T::default() {
46 T::REPRESENTABLE_MAX
47 } else {
48 diagnostic
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 #[test]
57 fn compatible_scope_restores_nested_panicking_and_other_thread_calls() {
58 assert_eq!(limit(256_000_000usize), 256_000_000);
59 {
60 let _outer = python_compatible();
61 assert_eq!(limit(256_000_000usize), usize::MAX);
62 assert_eq!(limit(0usize), 0); {
64 let _inner = python_compatible();
65 }
66 assert_eq!(limit(1000usize), usize::MAX);
67 assert_eq!(
68 std::thread::spawn(|| limit(1000usize)).join().unwrap(),
69 1000
70 );
71 }
72 let _ = std::panic::catch_unwind(|| {
73 let _scope = python_compatible();
74 panic!("deliberate scope unwind");
75 });
76 assert_eq!(limit(1000usize), 1000);
77 }
78}