Skip to main content

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    #[must_use]
33    pub fn new(kind: AMQPErrorKind, message: ShortString) -> Self {
34        Self { kind, message }
35    }
36
37    /// Get the error corresponding to an id
38    #[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    /// Get the kind of error
44    #[must_use]
45    pub fn kind(&self) -> &AMQPErrorKind {
46        &self.kind
47    }
48
49    /// Get the id of the error
50    #[must_use]
51    pub fn get_id(&self) -> Identifier {
52        self.kind.get_id()
53    }
54
55    /// Get the message of the error
56    #[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/// The kind of AMQP Error
89#[derive(Clone, Debug, PartialEq)]
90pub enum AMQPErrorKind {
91    /// A soft AMQP error
92    Soft(AMQPSoftError),
93    /// A hard AMQP error
94    Hard(AMQPHardError),
95}
96
97impl AMQPErrorKind {
98    /// Get the id of the error
99    #[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    /// Get the error kind corresponding to an id
108    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}