1use core::cell::UnsafeCell;
2use core::error::Error;
3use core::fmt;
4use core::marker::PhantomData;
5
6use super::{ContextError, ErrorMarker};
7
8mod sealed {
9 pub trait Sealed {}
10 impl Sealed for super::Ignore {}
11 impl<E> Sealed for super::Capture<E> {}
12 impl<E> Sealed for super::Emit<E> {}
13}
14
15pub trait ErrorMode<A>: self::sealed::Sealed {
23 #[doc(hidden)]
24 type Error;
25
26 #[doc(hidden)]
27 fn clear(&self);
28
29 #[doc(hidden)]
30 fn message<T>(&self, alloc: A, message: T) -> Self::Error
31 where
32 T: fmt::Display;
33
34 #[doc(hidden)]
35 fn custom<T>(&self, alloc: A, error: T) -> Self::Error
36 where
37 T: 'static + Send + Sync + Error;
38}
39
40#[non_exhaustive]
56pub struct Ignore;
57
58impl<A> ErrorMode<A> for Ignore {
59 type Error = ErrorMarker;
60
61 #[inline]
62 fn clear(&self) {}
63
64 #[inline]
65 fn message<T>(&self, alloc: A, message: T) -> Self::Error
66 where
67 T: fmt::Display,
68 {
69 _ = alloc;
70 _ = message;
71 ErrorMarker
72 }
73
74 #[inline]
75 fn custom<T>(&self, alloc: A, error: T) -> Self::Error
76 where
77 T: 'static + Send + Sync + Error,
78 {
79 _ = alloc;
80 _ = error;
81 ErrorMarker
82 }
83}
84
85pub struct Emit<E> {
91 _marker: PhantomData<E>,
92}
93
94impl<E> Emit<E> {
95 #[inline]
96 pub(super) fn new() -> Self {
97 Self {
98 _marker: PhantomData,
99 }
100 }
101}
102
103impl<E, A> ErrorMode<A> for Emit<E>
104where
105 E: ContextError<A>,
106{
107 type Error = E;
108
109 #[inline]
110 fn clear(&self) {}
111
112 #[inline]
113 fn message<T>(&self, alloc: A, message: T) -> Self::Error
114 where
115 T: fmt::Display,
116 {
117 E::message(alloc, message)
118 }
119
120 #[inline]
121 fn custom<T>(&self, alloc: A, error: T) -> Self::Error
122 where
123 T: 'static + Send + Sync + Error,
124 {
125 E::custom(alloc, error)
126 }
127}
128
129pub struct Capture<E> {
135 error: UnsafeCell<Option<E>>,
136}
137
138impl<E> Capture<E> {
139 #[inline]
140 pub(super) fn new() -> Self {
141 Self {
142 error: UnsafeCell::new(None),
143 }
144 }
145}
146
147impl<E> Capture<E> {
148 #[inline]
149 pub(super) fn unwrap(&self) -> E {
150 unsafe {
153 match (*self.error.get()).take() {
154 Some(error) => error,
155 None => panic!("no error captured"),
156 }
157 }
158 }
159
160 #[inline]
161 pub(super) fn result(&self) -> Result<(), E> {
162 unsafe {
165 match (*self.error.get()).take() {
166 Some(error) => Err(error),
167 None => Ok(()),
168 }
169 }
170 }
171}
172
173impl<E, A> ErrorMode<A> for Capture<E>
174where
175 E: ContextError<A>,
176{
177 type Error = ErrorMarker;
178
179 #[inline]
180 fn clear(&self) {
181 unsafe {
184 (*self.error.get()) = None;
185 }
186 }
187
188 #[inline]
189 fn message<T>(&self, alloc: A, message: T) -> Self::Error
190 where
191 T: fmt::Display,
192 {
193 unsafe {
196 (*self.error.get()) = Some(E::message(alloc, message));
197 }
198
199 ErrorMarker
200 }
201
202 #[inline]
203 fn custom<T>(&self, alloc: A, error: T) -> Self::Error
204 where
205 T: 'static + Send + Sync + Error,
206 {
207 unsafe {
210 (*self.error.get()) = Some(E::custom(alloc, error));
211 }
212
213 ErrorMarker
214 }
215}