1use core::fmt;
2use std::{error::Error, sync::Arc};
3
4use thiserror::Error;
5
6#[cfg(send_sync)]
7pub type ContextErrorSource = Box<dyn Error + Send + Sync + 'static>;
8#[cfg(not(send_sync))]
9pub type ContextErrorSource = Box<dyn Error + 'static>;
10
11#[derive(Debug, Error)]
12#[error(
13 "In {fn_ident}{}{}{}",
14 if self.label.is_empty() { "" } else { ", label = '" },
15 self.label,
16 if self.label.is_empty() { "" } else { "'" }
17)]
18pub struct ContextError {
19 pub fn_ident: &'static str,
20 #[source]
21 pub source: ContextErrorSource,
22 pub label: String,
23}
24
25#[derive(Clone)]
27pub struct MultiError {
28 inner: Vec<Arc<dyn Error + Send + Sync + 'static>>,
29}
30
31impl MultiError {
32 pub fn new<T: Error + Send + Sync + 'static>(
33 iter: impl ExactSizeIterator<Item = T>,
34 ) -> Option<Self> {
35 if iter.len() == 0 {
36 return None;
37 }
38 Some(Self {
39 inner: iter.map(Box::from).map(Arc::from).collect(),
40 })
41 }
42
43 pub fn errors(&self) -> Box<dyn Iterator<Item = &(dyn Error + Send + Sync + 'static)> + '_> {
44 Box::new(self.inner.iter().map(|e| e.as_ref()))
45 }
46}
47
48impl fmt::Debug for MultiError {
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
50 fmt::Debug::fmt(&self.inner[0], f)
51 }
52}
53
54impl fmt::Display for MultiError {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
56 fmt::Display::fmt(&self.inner[0], f)
57 }
58}
59
60impl Error for MultiError {
61 fn source(&self) -> Option<&(dyn Error + 'static)> {
62 self.inner[0].source()
63 }
64}