rabbitmq_stream_protocol/commands/
open.rs

1use std::{collections::HashMap, io::Write};
2
3use crate::{
4    codec::{Decoder, Encoder},
5    error::{DecodeError, EncodeError},
6    protocol::commands::COMMAND_OPEN,
7    response::ResponseCode,
8    FromResponse,
9};
10
11use super::Command;
12
13#[cfg_attr(test, derive(fake::Dummy))]
14#[derive(PartialEq, Eq, Debug)]
15pub struct OpenCommand {
16    correlation_id: u32,
17    virtual_host: String,
18}
19
20impl OpenCommand {
21    pub fn new(correlation_id: u32, virtual_host: String) -> Self {
22        Self {
23            correlation_id,
24            virtual_host,
25        }
26    }
27}
28
29impl Encoder for OpenCommand {
30    fn encode(&self, writer: &mut impl Write) -> Result<(), EncodeError> {
31        self.correlation_id.encode(writer)?;
32        self.virtual_host.as_str().encode(writer)?;
33        Ok(())
34    }
35
36    fn encoded_size(&self) -> u32 {
37        self.correlation_id.encoded_size() + self.virtual_host.as_str().encoded_size()
38    }
39}
40
41impl Command for OpenCommand {
42    fn key(&self) -> u16 {
43        COMMAND_OPEN
44    }
45}
46
47#[cfg_attr(test, derive(fake::Dummy))]
48#[derive(Debug, PartialEq, Eq)]
49pub struct OpenResponse {
50    pub(crate) correlation_id: u32,
51    pub(crate) code: ResponseCode,
52    pub connection_properties: HashMap<String, String>,
53}
54
55impl OpenResponse {
56    /// Get a reference to the generic response's code.
57    pub fn code(&self) -> &ResponseCode {
58        &self.code
59    }
60
61    pub fn is_ok(&self) -> bool {
62        self.code == ResponseCode::Ok
63    }
64}
65
66impl OpenResponse {
67    /// Get a reference to the open response's connection properties.
68    pub fn connection_properties(&self) -> &HashMap<String, String> {
69        &self.connection_properties
70    }
71}
72
73impl FromResponse for OpenResponse {
74    fn from_response(response: crate::Response) -> Option<Self> {
75        match response.kind {
76            crate::ResponseKind::Open(open) => Some(open),
77            _ => None,
78        }
79    }
80}
81
82impl Decoder for OpenResponse {
83    fn decode(input: &[u8]) -> Result<(&[u8], Self), DecodeError> {
84        let (input, correlation_id) = u32::decode(input)?;
85        let (input, response_code) = ResponseCode::decode(input)?;
86
87        let (input, connection_properties) = if response_code == ResponseCode::Ok {
88            HashMap::decode(input)?
89        } else {
90            (input, HashMap::new())
91        };
92
93        Ok((
94            input,
95            OpenResponse {
96                correlation_id,
97                code: response_code,
98                connection_properties,
99            },
100        ))
101    }
102}
103
104impl Decoder for OpenCommand {
105    fn decode(input: &[u8]) -> Result<(&[u8], Self), DecodeError> {
106        let (input, correlation_id) = u32::decode(input)?;
107        let (input, virtual_host) = Option::decode(input)?;
108
109        Ok((
110            input,
111            OpenCommand {
112                correlation_id,
113                virtual_host: virtual_host.unwrap(),
114            },
115        ))
116    }
117}
118
119#[cfg(test)]
120mod tests {
121
122    use fake::{Fake, Faker};
123
124    use super::OpenCommand;
125    use crate::{
126        codec::Encoder,
127        commands::{
128            open::OpenResponse,
129            tests::{command_encode_decode_test, specific_command_encode_decode_test},
130        },
131        ResponseCode,
132    };
133
134    #[test]
135    fn open_command_test() {
136        command_encode_decode_test::<OpenCommand>()
137    }
138
139    impl Encoder for OpenResponse {
140        fn encode(
141            &self,
142            writer: &mut impl std::io::Write,
143        ) -> Result<(), crate::error::EncodeError> {
144            self.correlation_id.encode(writer)?;
145            self.code.encode(writer)?;
146            self.connection_properties.encode(writer)?;
147            Ok(())
148        }
149
150        fn encoded_size(&self) -> u32 {
151            0
152        }
153    }
154
155    #[test]
156    fn open_response_test() {
157        let mut response: OpenResponse = Faker.fake();
158        response.code = ResponseCode::Ok;
159        specific_command_encode_decode_test(response);
160    }
161}