1use std::any::Any;
18
19use crate::deserialize::Deserialize;
20use crate::exceptions::ExceptionInfo;
21use crate::exceptions::ResultInfo;
22use crate::exceptions::ResultType;
23use crate::protocol::Field;
24use crate::protocol::ProtocolReader;
25use crate::protocol::ProtocolWriter;
26use crate::serialize::Serialize;
27use crate::thrift_protocol::ProtocolID;
28use crate::ttype::TType;
29use crate::Result;
30
31#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
33#[repr(i32)]
34pub enum ApplicationExceptionErrorCode {
35 #[default]
36 Unknown = 0,
37 UnknownMethod = 1,
38 InvalidMessageType = 2,
39 WrongMethodName = 3,
40 BadSequenceID = 4,
41 MissingResult = 5,
42 InternalError = 6,
43 ProtocolError = 7,
44 InvalidTransform = 8,
45 InvalidProtocol = 9,
46 UnsupportedClientType = 10,
47 Loadshedding = 11,
48 Timeout = 12,
49 InjectedFailure = 13,
50 ChecksumMismatch = 14,
51 Interruption = 15,
52}
53
54const TAPPLICATION_EXCEPTION_ERROR_CODE: &str = "ApplicationExceptionErrorCode";
55
56#[derive(
57 Debug,
58 Clone,
59 Eq,
60 PartialEq,
61 Ord,
62 PartialOrd,
63 Hash,
64 Default,
65 thiserror::Error
66)]
67#[error("{type_:?}: {message}")]
68pub struct ApplicationException {
69 pub message: String,
70 pub type_: ApplicationExceptionErrorCode,
71}
72
73impl ApplicationException {
74 #[cold]
75 pub fn new(type_: ApplicationExceptionErrorCode, message: String) -> Self {
76 ApplicationException { message, type_ }
77 }
78
79 #[cold]
81 pub fn unimplemented_method(handler: &str, method: &str) -> Self {
82 ApplicationException {
83 type_: ApplicationExceptionErrorCode::UnknownMethod,
84 message: format!("Method {} not implemented for {}", method, handler),
85 }
86 }
87
88 #[inline]
90 pub fn unknown_method() -> Self {
91 ApplicationException {
92 type_: ApplicationExceptionErrorCode::UnknownMethod,
93 message: String::new(), }
95 }
96
97 #[cold]
98 pub fn missing_arg(method: &str, arg: &str) -> Self {
99 ApplicationException {
100 type_: ApplicationExceptionErrorCode::ProtocolError,
101 message: format!("{} missing arg {}", method, arg),
102 }
103 }
104
105 #[cold]
106 pub fn missing_field(method: &str, field: &str) -> Self {
107 ApplicationException {
108 type_: ApplicationExceptionErrorCode::ProtocolError,
109 message: format!("Struct {} missing field {}", method, field),
110 }
111 }
112
113 #[cold]
114 pub fn invalid_protocol(badproto: ProtocolID) -> Self {
115 ApplicationException {
116 type_: ApplicationExceptionErrorCode::InvalidProtocol,
117 message: format!("Invalid protocol {:?}", badproto),
118 }
119 }
120
121 #[cold]
123 pub fn handler_panic(method: &str, exn: Box<dyn Any + Send + 'static>) -> Self {
124 ApplicationException {
125 type_: ApplicationExceptionErrorCode::Unknown,
126 message: format!(
127 "Handler for `{}` panicked with: {}",
128 method,
129 panic_message::get_panic_message(&exn).unwrap_or("<panic>")
130 ),
131 }
132 }
133}
134
135impl ExceptionInfo for ApplicationException {
136 #[rustfmt::skip]
137 fn exn_name(&self) -> &'static str {
138 match self.type_ {
139 ApplicationExceptionErrorCode::Unknown => "ApplicationExceptionErrorCode::Unknown",
140 ApplicationExceptionErrorCode::UnknownMethod => "ApplicationExceptionErrorCode::UnknownMethod",
141 ApplicationExceptionErrorCode::InvalidMessageType => "ApplicationExceptionErrorCode::InvalidMessageType",
142 ApplicationExceptionErrorCode::WrongMethodName => "ApplicationExceptionErrorCode::WrongMethodName",
143 ApplicationExceptionErrorCode::BadSequenceID => "ApplicationExceptionErrorCode::BadSequenceID",
144 ApplicationExceptionErrorCode::MissingResult => "ApplicationExceptionErrorCode::MissingResult",
145 ApplicationExceptionErrorCode::InternalError => "ApplicationExceptionErrorCode::InternalError",
146 ApplicationExceptionErrorCode::ProtocolError => "ApplicationExceptionErrorCode::ProtocolError",
147 ApplicationExceptionErrorCode::InvalidTransform => "ApplicationExceptionErrorCode::InvalidTransform",
148 ApplicationExceptionErrorCode::InvalidProtocol => "ApplicationExceptionErrorCode::InvalidProtocol",
149 ApplicationExceptionErrorCode::UnsupportedClientType => "ApplicationExceptionErrorCode::UnsupportedClientType",
150 ApplicationExceptionErrorCode::Loadshedding => "ApplicationExceptionErrorCode::Loadshedding",
151 ApplicationExceptionErrorCode::Timeout => "ApplicationExceptionErrorCode::Timeout",
152 ApplicationExceptionErrorCode::InjectedFailure => "ApplicationExceptionErrorCode::InjectedFailure",
153 ApplicationExceptionErrorCode::ChecksumMismatch => "ApplicationExceptionErrorCode::ChecksumMismatch",
154 ApplicationExceptionErrorCode::Interruption => "ApplicationExceptionErrorCode::Interruption",
155 }
156 }
157
158 fn exn_value(&self) -> String {
159 self.message.clone()
160 }
161
162 #[inline]
163 fn exn_is_declared(&self) -> bool {
164 false
165 }
166}
167
168impl ResultInfo for ApplicationException {
169 fn result_type(&self) -> ResultType {
170 ResultType::Exception
171 }
172}
173
174impl<P> Deserialize<P> for ApplicationException
175where
176 P: ProtocolReader,
177{
178 fn read(iprot: &mut P) -> Result<Self> {
180 iprot.read_struct_begin(|_| ())?;
181
182 let mut message = String::from("");
183 let mut type_ = ApplicationExceptionErrorCode::Unknown;
184
185 loop {
186 static FIELDS: &[Field] = &[
188 Field::new("message", TType::String, 1),
189 Field::new("type", TType::I32, 2),
190 ];
191 let (_, ttype, id) = iprot.read_field_begin(|_| (), FIELDS)?;
192
193 match (ttype, id) {
194 (TType::Stop, _) => break,
195 (TType::String, 1) => message = iprot.read_string()?,
196 (TType::I32, 2) => {
197 type_ = match iprot.read_i32()? {
198 1 => ApplicationExceptionErrorCode::UnknownMethod,
199 2 => ApplicationExceptionErrorCode::InvalidMessageType,
200 3 => ApplicationExceptionErrorCode::WrongMethodName,
201 4 => ApplicationExceptionErrorCode::BadSequenceID,
202 5 => ApplicationExceptionErrorCode::MissingResult,
203 6 => ApplicationExceptionErrorCode::InternalError,
204 7 => ApplicationExceptionErrorCode::ProtocolError,
205 8 => ApplicationExceptionErrorCode::InvalidTransform,
206 9 => ApplicationExceptionErrorCode::InvalidProtocol,
207 10 => ApplicationExceptionErrorCode::UnsupportedClientType,
208 11 => ApplicationExceptionErrorCode::Loadshedding,
209 12 => ApplicationExceptionErrorCode::Timeout,
210 13 => ApplicationExceptionErrorCode::InjectedFailure,
211 14 => ApplicationExceptionErrorCode::ChecksumMismatch,
212 15 => ApplicationExceptionErrorCode::Interruption,
213
214 _ => ApplicationExceptionErrorCode::Unknown,
215 }
216 }
217 (ttype, _) => iprot.skip(ttype)?,
218 };
219
220 iprot.read_field_end()?;
222 }
223 iprot.read_struct_end()?;
224 Ok(ApplicationException::new(type_, message))
225 }
226}
227
228impl<P> Serialize<P> for ApplicationException
229where
230 P: ProtocolWriter,
231{
232 fn write(&self, oprot: &mut P) {
234 oprot.write_struct_begin(TAPPLICATION_EXCEPTION_ERROR_CODE);
235
236 if !self.message.is_empty() {
237 oprot.write_field_begin("message", TType::String, 1);
238 oprot.write_string(&self.message);
239 oprot.write_field_end();
240 }
241 oprot.write_field_begin("type", TType::I32, 2);
242 oprot.write_i32(self.type_ as i32);
243 oprot.write_field_end();
244 oprot.write_field_stop();
245 oprot.write_struct_end();
246 }
247}