dcrypt_api/error/
registry.rs1use core::ptr::null_mut;
4use core::sync::atomic::{AtomicPtr, Ordering};
5
6pub static ERROR_REGISTRY: ErrorRegistry = ErrorRegistry::new();
8
9pub struct ErrorRegistry {
11 error: AtomicPtr<()>,
12}
13
14impl ErrorRegistry {
15 pub const fn new() -> Self {
17 Self {
18 error: AtomicPtr::new(null_mut()),
19 }
20 }
21
22 pub fn store<E>(&self, error: E) {
24 #[cfg(feature = "std")]
26 {
27 use std::boxed::Box;
28 let boxed = Box::into_raw(Box::new(error));
30 let old = self.error.swap(boxed as *mut (), Ordering::SeqCst);
31
32 if !old.is_null() {
34 unsafe {
35 drop(Box::from_raw(old));
36 }
37 }
38 }
39
40 #[cfg(not(feature = "std"))]
42 {
43 let _ = error; self.error.store(1 as *mut (), Ordering::SeqCst);
46 }
47 }
48
49 pub fn clear(&self) {
51 #[cfg(feature = "std")]
52 {
53 let ptr = self.error.swap(null_mut(), Ordering::SeqCst);
54 if !ptr.is_null() {
55 unsafe {
56 drop(Box::from_raw(ptr));
57 }
58 }
59 }
60
61 #[cfg(not(feature = "std"))]
62 {
63 self.error.store(null_mut(), Ordering::SeqCst);
64 }
65 }
66
67 pub fn has_error(&self) -> bool {
69 !self.error.load(Ordering::SeqCst).is_null()
70 }
71
72 #[cfg(feature = "std")]
74 pub fn get_error<E: Clone>(&self) -> Option<E> {
75 let ptr = self.error.load(Ordering::SeqCst);
76 if ptr.is_null() {
77 None
78 } else {
79 unsafe {
82 let error_ref = &*(ptr as *const E);
83 Some(error_ref.clone())
84 }
85 }
86 }
87}
88
89impl Default for ErrorRegistry {
90 fn default() -> Self {
91 Self::new()
92 }
93}
94
95impl Drop for ErrorRegistry {
96 fn drop(&mut self) {
97 self.clear();
98 }
99}