identity_core/common/
single_struct_error.rs1use std::borrow::Cow;
5use std::error::Error;
6use std::fmt::Debug;
7use std::fmt::Display;
8
9#[derive(Debug)]
19pub struct SingleStructError<T: Debug + Display> {
20 repr: Repr<T>,
21}
22
23impl<T: Display + Debug> Display for SingleStructError<T> {
24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 match self.repr {
26 Repr::Simple(ref kind) => write!(f, "{kind}"),
27 Repr::Extensive(ref extensive) => {
28 write!(f, "{}", &extensive.kind)?;
29 let Some(ref message) = extensive.message else {
30 return Ok(());
31 };
32 write!(f, " message: {}", message.as_ref())
33 }
34 }
35 }
36}
37
38impl<T: Debug + Display> Error for SingleStructError<T> {
39 fn source(&self) -> Option<&(dyn Error + 'static)> {
40 self.extensive().and_then(|err| {
41 err
42 .source
43 .as_ref()
44 .map(|source| source.as_ref() as &(dyn Error + 'static))
45 })
46 }
47}
48
49#[derive(Debug)]
50struct Extensive<T: Debug + Display> {
51 kind: T,
52 source: Option<Box<dyn Error + Send + Sync + 'static>>,
53 message: Option<Cow<'static, str>>,
54}
55
56#[derive(Debug)]
57enum Repr<T: Debug + Display> {
58 Simple(T),
59 Extensive(Box<Extensive<T>>),
60}
61
62impl<T: Debug + Display> From<T> for SingleStructError<T> {
63 fn from(kind: T) -> Self {
64 Self::new(kind)
65 }
66}
67
68impl<T: Debug + Display> From<Box<Extensive<T>>> for SingleStructError<T> {
69 fn from(extensive: Box<Extensive<T>>) -> Self {
70 Self {
71 repr: Repr::Extensive(extensive),
72 }
73 }
74}
75
76impl<T: Debug + Display> SingleStructError<T> {
77 pub fn new(kind: T) -> Self {
79 Self {
80 repr: Repr::Simple(kind),
81 }
82 }
83
84 pub fn kind(&self) -> &T {
86 match self.repr {
87 Repr::Simple(ref cause) => cause,
88 Repr::Extensive(ref extensive) => &extensive.kind,
89 }
90 }
91
92 pub fn into_kind(self) -> T {
94 match self.repr {
95 Repr::Simple(cause) => cause,
96 Repr::Extensive(extensive) => extensive.kind,
97 }
98 }
99
100 pub fn custom_message(&self) -> Option<&str> {
102 self
103 .extensive()
104 .into_iter()
105 .flat_map(|extensive| extensive.message.as_deref())
106 .next()
107 }
108
109 pub fn source_ref(&self) -> Option<&(dyn Error + Send + Sync + 'static)> {
111 self.extensive().and_then(|extensive| extensive.source.as_deref())
112 }
113
114 pub fn into_source(self) -> Option<Box<dyn Error + Send + Sync + 'static>> {
116 self.into_extensive().source
117 }
118
119 fn extensive(&self) -> Option<&Extensive<T>> {
120 match self.repr {
121 Repr::Extensive(ref extensive) => Some(extensive.as_ref()),
122 _ => None,
123 }
124 }
125
126 fn into_extensive(self) -> Box<Extensive<T>> {
127 match self.repr {
128 Repr::Extensive(extensive) => extensive,
129 Repr::Simple(kind) => Box::new(Extensive {
130 kind,
131 source: None,
132 message: None,
133 }),
134 }
135 }
136
137 pub fn with_source(self, source: impl Into<Box<dyn Error + Send + Sync + 'static>>) -> Self {
139 self._with_source(source.into())
140 }
141
142 fn _with_source(self, source: Box<dyn Error + Send + Sync + 'static>) -> Self {
143 let mut extensive = self.into_extensive();
144 extensive.as_mut().source = Some(source);
145 Self::from(extensive)
146 }
147
148 pub fn with_custom_message(self, message: impl Into<Cow<'static, str>>) -> Self {
150 self._with_custom_message(message.into())
151 }
152
153 fn _with_custom_message(self, message: Cow<'static, str>) -> Self {
154 let mut extensive = self.into_extensive();
155 extensive.as_mut().message = Some(message);
156 Self::from(extensive)
157 }
158}