1use crate::types::{
2 flags::*,
3 generation::*,
4 parsing::{traits::ParsableInput, *},
5 *,
6};
7use nom::{
8 Parser,
9 combinator::{flat_map, map, map_opt},
10 error::context,
11};
12use serde::{Deserialize, Serialize};
13use std::{convert::TryFrom, error, fmt, io::Write};
14
15#[cfg(feature = "codegen")]
16include!(concat!(env!("OUT_DIR"), "/protocol.rs"));
17#[cfg(not(feature = "codegen"))]
18include!("generated.rs");
19
20pub type BasicProperties = basic::AMQPProperties;
22
23#[derive(Clone, Debug, PartialEq)]
25pub struct AMQPError {
26 kind: AMQPErrorKind,
27 message: ShortString,
28}
29
30impl AMQPError {
31 #[must_use]
33 pub fn new(kind: AMQPErrorKind, message: ShortString) -> Self {
34 Self { kind, message }
35 }
36
37 #[must_use]
39 pub fn from_id(id: Identifier, message: ShortString) -> Option<Self> {
40 AMQPErrorKind::from_id(id).map(|kind| Self { kind, message })
41 }
42
43 #[must_use]
45 pub fn kind(&self) -> &AMQPErrorKind {
46 &self.kind
47 }
48
49 #[must_use]
51 pub fn get_id(&self) -> Identifier {
52 self.kind.get_id()
53 }
54
55 #[must_use]
57 pub fn get_message(&self) -> &ShortString {
58 &self.message
59 }
60}
61
62impl TryFrom<channel::Close> for AMQPError {
63 type Error = String;
64
65 fn try_from(method: channel::Close) -> Result<Self, Self::Error> {
66 Self::from_id(method.reply_code, method.reply_text.clone())
67 .ok_or_else(|| format!("Couldn't convert method to error: {method:?}"))
68 }
69}
70
71impl TryFrom<connection::Close> for AMQPError {
72 type Error = String;
73
74 fn try_from(method: connection::Close) -> Result<Self, Self::Error> {
75 Self::from_id(method.reply_code, method.reply_text.clone())
76 .ok_or_else(|| format!("Couldn't convert method to error: {method:?}"))
77 }
78}
79
80impl fmt::Display for AMQPError {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 write!(f, "{}: {}", self.kind, self.message)
83 }
84}
85
86impl error::Error for AMQPError {}
87
88#[derive(Clone, Debug, PartialEq)]
90pub enum AMQPErrorKind {
91 Soft(AMQPSoftError),
93 Hard(AMQPHardError),
95}
96
97impl AMQPErrorKind {
98 #[must_use]
100 pub fn get_id(&self) -> Identifier {
101 match *self {
102 AMQPErrorKind::Soft(ref s) => s.get_id(),
103 AMQPErrorKind::Hard(ref h) => h.get_id(),
104 }
105 }
106
107 pub fn from_id(id: Identifier) -> Option<Self> {
109 AMQPSoftError::from_id(id)
110 .map(AMQPErrorKind::Soft)
111 .or_else(|| AMQPHardError::from_id(id).map(AMQPErrorKind::Hard))
112 }
113}
114
115impl fmt::Display for AMQPErrorKind {
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117 match self {
118 AMQPErrorKind::Soft(err) => write!(f, "AMQP soft error: {err}"),
119 AMQPErrorKind::Hard(err) => write!(f, "AMQP hard error: {err}"),
120 }
121 }
122}
123
124impl From<AMQPSoftError> for AMQPErrorKind {
125 fn from(error: AMQPSoftError) -> Self {
126 Self::Soft(error)
127 }
128}
129
130impl From<AMQPHardError> for AMQPErrorKind {
131 fn from(error: AMQPHardError) -> Self {
132 Self::Hard(error)
133 }
134}
135
136#[cfg(test)]
137mod test {
138 use super::*;
139
140 #[test]
141 fn test_description() {
142 assert_eq!(
143 format!(
144 "{} - {}.{}.{}",
145 metadata::NAME,
146 metadata::MAJOR_VERSION,
147 metadata::MINOR_VERSION,
148 metadata::REVISION
149 ),
150 "AMQP - 0.9.1"
151 );
152 }
153}