1mod access;
6mod error_marker;
7mod rich_error;
8mod stack_context;
9#[cfg(feature = "alloc")]
10mod system_context;
11pub use self::error_marker::ErrorMarker;
12mod error;
13pub use self::error::Error;
14
15use core::cell::{Cell, UnsafeCell};
16use core::fmt;
17use core::marker::PhantomData;
18
19use musli::context::StdError;
20use musli::mode::Binary;
21use musli::{Allocator, Context};
22
23use crate::buf::{self, BufString};
24
25#[cfg(feature = "alloc")]
26pub use self::system_context::SystemContext;
27
28pub use self::stack_context::StackContext;
29
30pub use self::rich_error::RichError;
31
32pub struct Same<A, M, E> {
38 alloc: A,
39 _marker: PhantomData<(M, E)>,
40}
41
42impl<A, M, E> Same<A, M, E> {
43 pub fn new(alloc: A) -> Self {
45 Self {
46 alloc,
47 _marker: PhantomData,
48 }
49 }
50}
51
52impl<A> Same<A, Binary, ErrorMarker> {
53 #[inline]
55 #[doc(hidden)]
56 pub fn marker(alloc: A) -> Self {
57 Self::new(alloc)
58 }
59}
60
61impl<A, M, E> Default for Same<A, M, E>
62where
63 A: Default,
64{
65 #[inline]
66 fn default() -> Self {
67 Self {
68 alloc: A::default(),
69 _marker: PhantomData,
70 }
71 }
72}
73
74impl<A, M, E> Context for Same<A, M, E>
75where
76 A: Allocator,
77 E: Error,
78{
79 type Mode = M;
80 type Error = E;
81 type Mark = ();
82 type Buf<'this> = A::Buf<'this> where Self: 'this;
83 type BufString<'this> = BufString<A::Buf<'this>> where Self: 'this;
84
85 #[inline]
86 fn clear(&self) {}
87
88 #[inline]
89 fn alloc(&self) -> Option<Self::Buf<'_>> {
90 self.alloc.alloc()
91 }
92
93 #[inline]
94 fn collect_string<T>(&self, value: &T) -> Result<Self::BufString<'_>, Self::Error>
95 where
96 T: ?Sized + fmt::Display,
97 {
98 buf::collect_string(self, value)
99 }
100
101 #[inline]
102 fn custom<T>(&self, message: T) -> Self::Error
103 where
104 T: 'static + Send + Sync + StdError,
105 {
106 E::custom(message)
107 }
108
109 #[inline]
110 fn message<T>(&self, message: T) -> Self::Error
111 where
112 T: fmt::Display,
113 {
114 E::message(message)
115 }
116}
117
118pub struct Ignore<A, M, E> {
121 alloc: A,
122 error: Cell<bool>,
123 _marker: PhantomData<(M, E)>,
124}
125
126impl<A, M, E> Default for Ignore<A, M, E>
127where
128 A: Default,
129{
130 #[inline]
131 fn default() -> Self {
132 Self {
133 alloc: A::default(),
134 error: Cell::new(false),
135 _marker: PhantomData,
136 }
137 }
138}
139
140impl<A, M, E> Ignore<A, M, E> {
141 pub fn new(alloc: A) -> Self {
143 Self {
144 alloc,
145 error: Cell::new(false),
146 _marker: PhantomData,
147 }
148 }
149}
150
151impl<A> Ignore<A, Binary, ErrorMarker> {
152 #[doc(hidden)]
154 pub fn marker(alloc: A) -> Self {
155 Self::new(alloc)
156 }
157}
158
159impl<A, M, E> Ignore<A, M, E>
160where
161 E: Error,
162{
163 pub fn unwrap(self) -> E {
165 if self.error.get() {
166 return E::message("error");
167 }
168
169 panic!("did not error")
170 }
171}
172
173impl<A, M, E: 'static> Context for Ignore<A, M, E>
174where
175 A: Allocator,
176{
177 type Mode = M;
178 type Error = ErrorMarker;
179 type Mark = ();
180 type Buf<'this> = A::Buf<'this> where Self: 'this;
181 type BufString<'this> = BufString<A::Buf<'this>> where Self: 'this;
182
183 #[inline]
184 fn clear(&self) {}
185
186 #[inline]
187 fn alloc(&self) -> Option<Self::Buf<'_>> {
188 self.alloc.alloc()
189 }
190
191 #[inline]
192 fn collect_string<T>(&self, value: &T) -> Result<Self::BufString<'_>, Self::Error>
193 where
194 T: ?Sized + fmt::Display,
195 {
196 buf::collect_string(self, value)
197 }
198
199 #[inline]
200 fn custom<T>(&self, _: T) -> ErrorMarker
201 where
202 T: 'static + Send + Sync + fmt::Display + fmt::Debug,
203 {
204 self.error.set(true);
205 ErrorMarker
206 }
207
208 #[inline]
209 fn message<T>(&self, _: T) -> ErrorMarker
210 where
211 T: fmt::Display,
212 {
213 self.error.set(true);
214 ErrorMarker
215 }
216}
217
218pub struct Capture<A, M, E> {
220 alloc: A,
221 error: UnsafeCell<Option<E>>,
222 _marker: PhantomData<M>,
223}
224
225impl<A, M, E> Capture<A, M, E> {
226 pub fn new(alloc: A) -> Self {
228 Self {
229 alloc,
230 error: UnsafeCell::new(None),
231 _marker: PhantomData,
232 }
233 }
234
235 pub fn unwrap(self) -> E {
237 if let Some(error) = self.error.into_inner() {
238 return error;
239 }
240
241 panic!("no error captured")
242 }
243}
244
245impl<A, M, E> Context for Capture<A, M, E>
246where
247 A: Allocator,
248 E: Error,
249{
250 type Mode = M;
251 type Error = ErrorMarker;
252 type Mark = ();
253 type Buf<'this> = A::Buf<'this> where Self: 'this;
254 type BufString<'this> = BufString<A::Buf<'this>> where Self: 'this;
255
256 #[inline]
257 fn clear(&self) {
258 unsafe {
261 (*self.error.get()) = None;
262 }
263 }
264
265 #[inline]
266 fn alloc(&self) -> Option<Self::Buf<'_>> {
267 self.alloc.alloc()
268 }
269
270 #[inline]
271 fn collect_string<T>(&self, value: &T) -> Result<Self::BufString<'_>, Self::Error>
272 where
273 T: ?Sized + fmt::Display,
274 {
275 buf::collect_string(self, value)
276 }
277
278 #[inline]
279 fn custom<T>(&self, error: T) -> ErrorMarker
280 where
281 T: 'static + Send + Sync + StdError,
282 {
283 unsafe {
286 self.error.get().replace(Some(E::custom(error)));
287 }
288
289 ErrorMarker
290 }
291
292 #[inline]
293 fn message<T>(&self, message: T) -> ErrorMarker
294 where
295 T: fmt::Display,
296 {
297 unsafe {
300 self.error.get().replace(Some(E::message(message)));
301 }
302
303 ErrorMarker
304 }
305}
306
307impl<A, M, E> Default for Capture<A, M, E>
308where
309 A: Default,
310{
311 #[inline]
312 fn default() -> Self {
313 Self::new(A::default())
314 }
315}