1use super::message_ops::Sealed;
2use super::{Message, MessageKind, MessageOps};
3use crate::error::{DeserializeError, SerializeError};
4use crate::message_deserializer::{MessageDeserializeError, MessageWithValueDeserializer};
5use crate::message_serializer::{MessageSerializeError, MessageSerializer};
6use crate::serialized_value::{SerializedValue, SerializedValueSlice};
7use crate::value_deserializer::{Deserialize, Deserializer};
8use crate::value_serializer::{Serialize, Serializer};
9use bytes::BytesMut;
10use num_enum::{IntoPrimitive, TryFromPrimitive};
11
12#[derive(Debug, Clone, PartialEq, Eq, Default)]
13#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))]
14pub struct ConnectReplyData {
15 pub user: Option<SerializedValue>,
16}
17
18impl ConnectReplyData {
19 pub fn new() -> Self {
20 Self::default()
21 }
22
23 pub fn serialize_user<T: Serialize + ?Sized>(
24 &mut self,
25 user: &T,
26 ) -> Result<&mut Self, SerializeError> {
27 self.user = SerializedValue::serialize(user).map(Some)?;
28 Ok(self)
29 }
30
31 pub fn deserialize_user<T: Deserialize>(&self) -> Option<Result<T, DeserializeError>> {
32 self.user.as_deref().map(SerializedValueSlice::deserialize)
33 }
34}
35
36impl Serialize for ConnectReplyData {
37 fn serialize(&self, serializer: Serializer) -> Result<(), SerializeError> {
38 let mut serializer = serializer.serialize_struct(1)?;
39 serializer.serialize_field(0, &self.user)?;
40 serializer.finish()
41 }
42}
43
44impl Deserialize for ConnectReplyData {
45 fn deserialize(deserializer: Deserializer) -> Result<Self, DeserializeError> {
46 let mut deserializer = deserializer.deserialize_struct()?;
47
48 let mut user = None;
49
50 while deserializer.has_more_fields() {
51 let deserializer = deserializer.deserialize_field()?;
52
53 match deserializer.id() {
54 0 => user = deserializer.deserialize()?,
55 _ => deserializer.skip()?,
56 }
57 }
58
59 Ok(Self { user })
60 }
61}
62
63#[derive(Debug, Copy, Clone, PartialEq, Eq, IntoPrimitive, TryFromPrimitive)]
64#[repr(u8)]
65enum ConnectReplyKind {
66 Ok = 0,
67 Rejected = 1,
68 IncompatibleVersion = 2,
69}
70
71#[derive(Debug, Copy, Clone, PartialEq, Eq)]
72#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))]
73pub enum ConnectResult {
74 Ok(u32),
75 Rejected,
76 IncompatibleVersion,
77}
78
79#[derive(Debug, Clone, PartialEq, Eq)]
80#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))]
81pub struct ConnectReply2 {
82 pub result: ConnectResult,
83 pub value: SerializedValue,
84}
85
86impl ConnectReply2 {
87 pub fn ok_with_serialize_data(
88 version: u32,
89 data: &ConnectReplyData,
90 ) -> Result<Self, SerializeError> {
91 let value = SerializedValue::serialize(data)?;
92
93 Ok(Self {
94 result: ConnectResult::Ok(version),
95 value,
96 })
97 }
98
99 pub fn rejected_with_serialize_data(data: &ConnectReplyData) -> Result<Self, SerializeError> {
100 let value = SerializedValue::serialize(data)?;
101
102 Ok(Self {
103 result: ConnectResult::Rejected,
104 value,
105 })
106 }
107
108 pub fn incompatible_version_with_serialize_data(
109 data: &ConnectReplyData,
110 ) -> Result<Self, SerializeError> {
111 let value = SerializedValue::serialize(data)?;
112
113 Ok(Self {
114 result: ConnectResult::IncompatibleVersion,
115 value,
116 })
117 }
118
119 pub fn deserialize_connect_data(&self) -> Result<ConnectReplyData, DeserializeError> {
120 self.value.deserialize()
121 }
122}
123
124impl MessageOps for ConnectReply2 {
125 fn kind(&self) -> MessageKind {
126 MessageKind::ConnectReply2
127 }
128
129 fn serialize_message(self) -> Result<BytesMut, MessageSerializeError> {
130 let mut serializer = MessageSerializer::with_value(self.value, MessageKind::ConnectReply2)?;
131
132 match self.result {
133 ConnectResult::Ok(version) => {
134 serializer.put_discriminant_u8(ConnectReplyKind::Ok);
135 serializer.put_varint_u32_le(version);
136 serializer.finish()
137 }
138
139 ConnectResult::Rejected => {
140 serializer.put_discriminant_u8(ConnectReplyKind::Rejected);
141 serializer.finish()
142 }
143
144 ConnectResult::IncompatibleVersion => {
145 serializer.put_discriminant_u8(ConnectReplyKind::IncompatibleVersion);
146 serializer.finish()
147 }
148 }
149 }
150
151 fn deserialize_message(buf: BytesMut) -> Result<Self, MessageDeserializeError> {
152 let mut deserializer = MessageWithValueDeserializer::new(buf, MessageKind::ConnectReply2)?;
153
154 match deserializer.try_get_discriminant_u8()? {
155 ConnectReplyKind::Ok => {
156 let version = deserializer.try_get_varint_u32_le()?;
157 let value = deserializer.finish()?;
158
159 Ok(Self {
160 result: ConnectResult::Ok(version),
161 value,
162 })
163 }
164
165 ConnectReplyKind::Rejected => {
166 let value = deserializer.finish()?;
167
168 Ok(Self {
169 result: ConnectResult::Rejected,
170 value,
171 })
172 }
173
174 ConnectReplyKind::IncompatibleVersion => {
175 let value = deserializer.finish()?;
176
177 Ok(Self {
178 result: ConnectResult::IncompatibleVersion,
179 value,
180 })
181 }
182 }
183 }
184
185 fn value(&self) -> Option<&SerializedValueSlice> {
186 Some(&self.value)
187 }
188}
189
190impl Sealed for ConnectReply2 {}
191
192impl From<ConnectReply2> for Message {
193 fn from(msg: ConnectReply2) -> Self {
194 Self::ConnectReply2(msg)
195 }
196}
197
198#[cfg(test)]
199mod test {
200 use super::super::test::{assert_deserialize_eq_with_value, assert_serialize_eq};
201 use super::super::Message;
202 use super::{ConnectReply2, ConnectReplyData};
203
204 #[test]
205 fn ok() {
206 let serialized = [15, 0, 0, 0, 47, 4, 0, 0, 0, 39, 1, 0, 0, 0, 1];
207 let value = ConnectReplyData::new();
208
209 let msg = ConnectReply2::ok_with_serialize_data(1, &value).unwrap();
210 assert_serialize_eq(&msg, serialized);
211 assert_deserialize_eq_with_value(&msg, serialized, &value);
212
213 let msg = Message::ConnectReply2(msg);
214 assert_serialize_eq(&msg, serialized);
215 assert_deserialize_eq_with_value(&msg, serialized, &value);
216 }
217
218 #[test]
219 fn rejected() {
220 let serialized = [14, 0, 0, 0, 47, 4, 0, 0, 0, 39, 1, 0, 0, 1];
221 let value = ConnectReplyData::new();
222
223 let msg = ConnectReply2::rejected_with_serialize_data(&value).unwrap();
224 assert_serialize_eq(&msg, serialized);
225 assert_deserialize_eq_with_value(&msg, serialized, &value);
226
227 let msg = Message::ConnectReply2(msg);
228 assert_serialize_eq(&msg, serialized);
229 assert_deserialize_eq_with_value(&msg, serialized, &value);
230 }
231
232 #[test]
233 fn incompatible_version() {
234 let serialized = [14, 0, 0, 0, 47, 4, 0, 0, 0, 39, 1, 0, 0, 2];
235 let value = ConnectReplyData::new();
236
237 let msg = ConnectReply2::incompatible_version_with_serialize_data(&value).unwrap();
238 assert_serialize_eq(&msg, serialized);
239 assert_deserialize_eq_with_value(&msg, serialized, &value);
240
241 let msg = Message::ConnectReply2(msg);
242 assert_serialize_eq(&msg, serialized);
243 assert_deserialize_eq_with_value(&msg, serialized, &value);
244 }
245}