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