Skip to main content

ntex_amqp_codec/codec/
mod.rs

1use ntex_bytes::{Buf, Bytes, BytesMut};
2
3use crate::{error::AmqpParseError, types::Constructor, types::Descriptor};
4
5macro_rules! decode_check_len {
6    ($buf:ident, $size:expr) => {
7        if $buf.len() < $size {
8            return Err(AmqpParseError::Incomplete($size));
9        }
10    };
11}
12
13#[macro_use]
14pub(crate) mod decode;
15mod encode;
16
17/// Defines routines to encode the type as an AMQP value. Encoding must include the type constructor (format code or described type definition).
18pub trait Encode {
19    /// Returns the size of the type when encoded.
20    fn encoded_size(&self) -> usize;
21
22    /// Encodes the type into the provided buffer.
23    fn encode(&self, buf: &mut BytesMut);
24}
25
26/// Defines routines to encode the type as an element of an AMQP array. It's different from Encode in that it omits the type constructor
27/// (format code or described type definition) when encoding.
28pub trait ArrayEncode {
29    const ARRAY_CONSTRUCTOR: Constructor;
30
31    /// Returns the size of the type when encoded as an element of an AMQP array.
32    fn array_encoded_size(&self) -> usize;
33
34    /// Encodes the type as an element of an AMQP array.
35    fn array_encode(&self, buf: &mut BytesMut);
36}
37
38pub trait Composite: Encode + Decode {
39    fn descriptor() -> Descriptor;
40}
41
42/// Defines routines to decode the type from an encoded AMQP value representation. Decoding must handle parsing the type constructor
43/// (format code or described type definition).
44pub trait Decode
45where
46    Self: Sized,
47{
48    /// Decodes the type from the provided buffer.
49    fn decode(input: &mut Bytes) -> Result<Self, AmqpParseError>;
50}
51
52pub trait DecodeFormatted
53where
54    Self: Sized,
55{
56    fn decode_with_format(input: &mut Bytes, fmt: u8) -> Result<Self, AmqpParseError>;
57}
58
59impl<T: DecodeFormatted> Decode for T {
60    fn decode(input: &mut Bytes) -> Result<Self, AmqpParseError> {
61        let fmt = decode_format_code(input)?;
62        T::decode_with_format(input, fmt)
63    }
64}
65
66pub(crate) fn decode_format_code(input: &mut Bytes) -> Result<u8, AmqpParseError> {
67    decode_check_len!(input, 1);
68    let code = input.get_u8();
69    Ok(code)
70}
71
72pub mod format_codes {
73    pub const FORMATCODE_DESCRIBED: u8 = 0x00;
74    pub const FORMATCODE_NULL: u8 = 0x40; // fixed width --V
75    pub const FORMATCODE_BOOLEAN: u8 = 0x56;
76    pub const FORMATCODE_BOOLEAN_TRUE: u8 = 0x41;
77    pub const FORMATCODE_BOOLEAN_FALSE: u8 = 0x42;
78    pub const FORMATCODE_UINT_0: u8 = 0x43;
79    pub const FORMATCODE_ULONG_0: u8 = 0x44;
80    pub const FORMATCODE_UBYTE: u8 = 0x50;
81    pub const FORMATCODE_USHORT: u8 = 0x60;
82    pub const FORMATCODE_UINT: u8 = 0x70;
83    pub const FORMATCODE_ULONG: u8 = 0x80;
84    pub const FORMATCODE_BYTE: u8 = 0x51;
85    pub const FORMATCODE_SHORT: u8 = 0x61;
86    pub const FORMATCODE_INT: u8 = 0x71;
87    pub const FORMATCODE_LONG: u8 = 0x81;
88    pub const FORMATCODE_SMALLUINT: u8 = 0x52;
89    pub const FORMATCODE_SMALLULONG: u8 = 0x53;
90    pub const FORMATCODE_SMALLINT: u8 = 0x54;
91    pub const FORMATCODE_SMALLLONG: u8 = 0x55;
92    pub const FORMATCODE_FLOAT: u8 = 0x72;
93    pub const FORMATCODE_DOUBLE: u8 = 0x82;
94    pub const FORMATCODE_DECIMAL32: u8 = 0x74;
95    pub const FORMATCODE_DECIMAL64: u8 = 0x84;
96    pub const FORMATCODE_DECIMAL128: u8 = 0x94;
97    pub const FORMATCODE_CHAR: u8 = 0x73;
98    pub const FORMATCODE_TIMESTAMP: u8 = 0x83;
99    pub const FORMATCODE_UUID: u8 = 0x98;
100    pub const FORMATCODE_BINARY8: u8 = 0xa0; // variable --V
101    pub const FORMATCODE_BINARY32: u8 = 0xb0;
102    pub const FORMATCODE_STRING8: u8 = 0xa1;
103    pub const FORMATCODE_STRING32: u8 = 0xb1;
104    pub const FORMATCODE_SYMBOL8: u8 = 0xa3;
105    pub const FORMATCODE_SYMBOL32: u8 = 0xb3;
106    pub const FORMATCODE_LIST0: u8 = 0x45; // compound --V
107    pub const FORMATCODE_LIST8: u8 = 0xc0;
108    pub const FORMATCODE_LIST32: u8 = 0xd0;
109    pub const FORMATCODE_MAP8: u8 = 0xc1;
110    pub const FORMATCODE_MAP32: u8 = 0xd1;
111    pub const FORMATCODE_ARRAY8: u8 = 0xe0;
112    pub const FORMATCODE_ARRAY32: u8 = 0xf0;
113}
114
115pub(crate) use self::format_codes::*;
116
117#[derive(Copy, Clone, Debug)]
118pub struct ListHeader {
119    pub size: u32,
120    pub count: u32,
121}
122
123#[derive(Copy, Clone, Debug)]
124pub struct MapHeader {
125    pub size: u32,
126    pub count: u32,
127}
128
129#[derive(Copy, Clone, Debug)]
130pub struct ArrayHeader {
131    pub size: u32,
132    pub count: u32,
133}
134
135#[cfg(test)]
136mod tests {
137    use ntex_bytes::{Bytes, BytesMut};
138
139    use crate::codec::{Decode, Encode};
140    use crate::error::AmqpCodecError;
141    use crate::framing::{AmqpFrame, SaslFrame};
142    use crate::protocol::SaslFrameBody;
143
144    #[test]
145    fn test_sasl_mechanisms() -> Result<(), AmqpCodecError> {
146        let mut data = Bytes::from_static(
147            b"\x02\x01\0\0\0S@\xc02\x01\xe0/\x04\xb3\0\0\0\x07MSSBCBS\0\0\0\x05PLAIN\0\0\0\tANONYMOUS\0\0\0\x08EXTERNAL");
148
149        let data2 = data.clone();
150        let frame = SaslFrame::decode(&mut data).unwrap();
151        assert!(data.is_empty());
152        match frame.body {
153            SaslFrameBody::SaslMechanisms(_) => (),
154            _ => panic!("error"),
155        }
156
157        let mut buf = BytesMut::new();
158        buf.reserve(frame.encoded_size());
159        frame.encode(&mut buf);
160        buf.advance_to(4);
161        assert_eq!(data2, buf.freeze());
162
163        Ok(())
164    }
165
166    #[test]
167    fn test_disposition() -> Result<(), AmqpCodecError> {
168        let data = Bytes::from_static(b"\x02\0\0\0\0S\x15\xc0\x0c\x06AC@A\0S$\xc0\x01\0B");
169
170        let frame = AmqpFrame::decode(&mut data.clone())?;
171        assert_eq!(frame.performative().name(), "Disposition");
172
173        let mut buf = BytesMut::new();
174        buf.reserve(frame.encoded_size());
175        frame.encode(&mut buf);
176        buf.advance_to(4);
177        assert_eq!(data, buf.freeze());
178
179        Ok(())
180    }
181}