amq_protocol/
protocol.rs

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
20/// Type alias for AMQP BasicProperties
21pub type BasicProperties = basic::AMQPProperties;
22
23/// An AMQP Error
24#[derive(Clone, Debug, PartialEq)]
25pub struct AMQPError {
26    kind: AMQPErrorKind,
27    message: ShortString,
28}
29
30impl AMQPError {
31    /// Create a new error
32    pub fn new(kind: AMQPErrorKind, message: ShortString) -> Self {
33        Self { kind, message }
34    }
35
36    /// Get the error corresponding to an id
37    pub fn from_id(id: Identifier, message: ShortString) -> Option<Self> {
38        AMQPErrorKind::from_id(id).map(|kind| Self { kind, message })
39    }
40
41    /// Get the kind of error
42    pub fn kind(&self) -> &AMQPErrorKind {
43        &self.kind
44    }
45
46    /// Get the id of the error
47    pub fn get_id(&self) -> Identifier {
48        self.kind.get_id()
49    }
50
51    /// Get the message of the error
52    pub fn get_message(&self) -> &ShortString {
53        &self.message
54    }
55}
56
57impl TryFrom<channel::Close> for AMQPError {
58    type Error = String;
59
60    fn try_from(method: channel::Close) -> Result<Self, Self::Error> {
61        Self::from_id(method.reply_code, method.reply_text.clone())
62            .ok_or_else(|| format!("Couldn't convert method to error: {method:?}"))
63    }
64}
65
66impl TryFrom<connection::Close> for AMQPError {
67    type Error = String;
68
69    fn try_from(method: connection::Close) -> Result<Self, Self::Error> {
70        Self::from_id(method.reply_code, method.reply_text.clone())
71            .ok_or_else(|| format!("Couldn't convert method to error: {method:?}"))
72    }
73}
74
75impl fmt::Display for AMQPError {
76    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77        write!(f, "{}: {}", self.kind, self.message)
78    }
79}
80
81impl error::Error for AMQPError {}
82
83/// The kind of AMQP Error
84#[derive(Clone, Debug, PartialEq)]
85pub enum AMQPErrorKind {
86    /// A soft AMQP error
87    Soft(AMQPSoftError),
88    /// A hard AMQP error
89    Hard(AMQPHardError),
90}
91
92impl AMQPErrorKind {
93    /// Get the id of the error
94    pub fn get_id(&self) -> Identifier {
95        match *self {
96            AMQPErrorKind::Soft(ref s) => s.get_id(),
97            AMQPErrorKind::Hard(ref h) => h.get_id(),
98        }
99    }
100
101    /// Get the error kind corresponding to an id
102    pub fn from_id(id: Identifier) -> Option<Self> {
103        AMQPSoftError::from_id(id)
104            .map(AMQPErrorKind::Soft)
105            .or_else(|| AMQPHardError::from_id(id).map(AMQPErrorKind::Hard))
106    }
107}
108
109impl fmt::Display for AMQPErrorKind {
110    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111        match self {
112            AMQPErrorKind::Soft(err) => write!(f, "AMQP soft error: {err}"),
113            AMQPErrorKind::Hard(err) => write!(f, "AMQP hard error: {err}"),
114        }
115    }
116}
117
118impl From<AMQPSoftError> for AMQPErrorKind {
119    fn from(error: AMQPSoftError) -> Self {
120        Self::Soft(error)
121    }
122}
123
124impl From<AMQPHardError> for AMQPErrorKind {
125    fn from(error: AMQPHardError) -> Self {
126        Self::Hard(error)
127    }
128}
129
130#[cfg(test)]
131mod test {
132    use super::*;
133
134    #[test]
135    fn test_description() {
136        assert_eq!(
137            format!(
138                "{} - {}.{}.{}",
139                metadata::NAME,
140                metadata::MAJOR_VERSION,
141                metadata::MINOR_VERSION,
142                metadata::REVISION
143            ),
144            "AMQP - 0.9.1"
145        );
146    }
147}