1use std::{error, fmt, panic::Location, sync::Arc};
2
3use crate::{Backtrace, Error, ErrorDiagnostic, ErrorKind, ErrorRepr};
4
5#[derive(Debug, Clone)]
6pub struct ErrorChain<K: ErrorKind> {
7 error: Arc<dyn ErrorDiagnostic<Kind = K>>,
8}
9
10impl<K: ErrorKind> ErrorChain<K> {
11 #[track_caller]
12 pub fn new<E>(error: E) -> Self
13 where
14 E: ErrorDiagnostic + Sized,
15 K: ErrorKind + From<E::Kind>,
16 {
17 Self {
18 error: Arc::new(ErrorRepr::new(error, None, Location::caller())),
19 }
20 }
21}
22
23impl<E, K> From<Error<E>> for ErrorChain<K>
24where
25 E: ErrorDiagnostic<Kind = K> + Sized,
26 K: ErrorKind,
27{
28 fn from(err: Error<E>) -> Self {
29 Self { error: err.inner }
30 }
31}
32
33impl<K> error::Error for ErrorChain<K>
34where
35 K: ErrorKind,
36{
37 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
38 self.error.source()
39 }
40}
41
42impl<K> fmt::Display for ErrorChain<K>
43where
44 K: ErrorKind,
45{
46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47 fmt::Display::fmt(&self.error, f)
48 }
49}
50
51impl<K> ErrorDiagnostic for ErrorChain<K>
52where
53 K: ErrorKind,
54{
55 type Kind = K;
56
57 fn kind(&self) -> Self::Kind {
58 self.error.kind()
59 }
60
61 fn service(&self) -> Option<&'static str> {
62 self.error.service()
63 }
64
65 fn signature(&self) -> &'static str {
66 self.error.signature()
67 }
68
69 fn backtrace(&self) -> Option<&Backtrace> {
70 self.error.backtrace()
71 }
72}