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::{AsSerializeArg, 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
36#[derive(IntoPrimitive, TryFromPrimitive)]
37#[repr(u32)]
38enum ConnectReplyDataField {
39 User = 0,
40}
41
42impl Serialize for ConnectReplyData {
43 fn serialize(&self, serializer: Serializer) -> Result<(), SerializeError> {
44 let mut serializer = serializer.serialize_struct(1)?;
45 serializer.serialize_field(ConnectReplyDataField::User, &self.user)?;
46 serializer.finish()
47 }
48}
49
50impl Deserialize for ConnectReplyData {
51 fn deserialize(deserializer: Deserializer) -> Result<Self, DeserializeError> {
52 let mut deserializer = deserializer.deserialize_struct()?;
53
54 let mut user = None;
55
56 while deserializer.has_more_fields() {
57 let deserializer = deserializer.deserialize_field()?;
58
59 let Ok(field) = deserializer.try_id() else {
60 deserializer.skip()?;
61 continue;
62 };
63
64 match field {
65 ConnectReplyDataField::User => user = deserializer.deserialize()?,
66 }
67 }
68
69 deserializer.finish(Self { user })
70 }
71}
72
73impl AsSerializeArg for ConnectReplyData {
74 type SerializeArg<'a> = &'a Self;
75
76 fn as_serialize_arg<'a>(&'a self) -> Self::SerializeArg<'a>
77 where
78 Self: 'a,
79 {
80 self
81 }
82}
83
84#[derive(Debug, Copy, Clone, PartialEq, Eq, IntoPrimitive, TryFromPrimitive)]
85#[repr(u8)]
86enum ConnectReplyKind {
87 Ok = 0,
88 Rejected = 1,
89 IncompatibleVersion = 2,
90}
91
92#[derive(Debug, Copy, Clone, PartialEq, Eq)]
93#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))]
94pub enum ConnectResult {
95 Ok(u32),
96 Rejected,
97 IncompatibleVersion,
98}
99
100#[derive(Debug, Clone, PartialEq, Eq)]
101#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))]
102pub struct ConnectReply2 {
103 pub result: ConnectResult,
104 pub value: SerializedValue,
105}
106
107impl ConnectReply2 {
108 pub fn ok_with_serialize_data(
109 version: u32,
110 data: &ConnectReplyData,
111 ) -> Result<Self, SerializeError> {
112 let value = SerializedValue::serialize(data)?;
113
114 Ok(Self {
115 result: ConnectResult::Ok(version),
116 value,
117 })
118 }
119
120 pub fn rejected_with_serialize_data(data: &ConnectReplyData) -> Result<Self, SerializeError> {
121 let value = SerializedValue::serialize(data)?;
122
123 Ok(Self {
124 result: ConnectResult::Rejected,
125 value,
126 })
127 }
128
129 pub fn incompatible_version_with_serialize_data(
130 data: &ConnectReplyData,
131 ) -> Result<Self, SerializeError> {
132 let value = SerializedValue::serialize(data)?;
133
134 Ok(Self {
135 result: ConnectResult::IncompatibleVersion,
136 value,
137 })
138 }
139
140 pub fn deserialize_connect_data(&self) -> Result<ConnectReplyData, DeserializeError> {
141 self.value.deserialize()
142 }
143}
144
145impl MessageOps for ConnectReply2 {
146 fn kind(&self) -> MessageKind {
147 MessageKind::ConnectReply2
148 }
149
150 fn serialize_message(self) -> Result<BytesMut, MessageSerializeError> {
151 let mut serializer = MessageSerializer::with_value(self.value, MessageKind::ConnectReply2)?;
152
153 match self.result {
154 ConnectResult::Ok(version) => {
155 serializer.put_discriminant_u8(ConnectReplyKind::Ok);
156 serializer.put_varint_u32_le(version);
157 serializer.finish()
158 }
159
160 ConnectResult::Rejected => {
161 serializer.put_discriminant_u8(ConnectReplyKind::Rejected);
162 serializer.finish()
163 }
164
165 ConnectResult::IncompatibleVersion => {
166 serializer.put_discriminant_u8(ConnectReplyKind::IncompatibleVersion);
167 serializer.finish()
168 }
169 }
170 }
171
172 fn deserialize_message(buf: BytesMut) -> Result<Self, MessageDeserializeError> {
173 let mut deserializer = MessageWithValueDeserializer::new(buf, MessageKind::ConnectReply2)?;
174
175 match deserializer.try_get_discriminant_u8()? {
176 ConnectReplyKind::Ok => {
177 let version = deserializer.try_get_varint_u32_le()?;
178 let value = deserializer.finish()?;
179
180 Ok(Self {
181 result: ConnectResult::Ok(version),
182 value,
183 })
184 }
185
186 ConnectReplyKind::Rejected => {
187 let value = deserializer.finish()?;
188
189 Ok(Self {
190 result: ConnectResult::Rejected,
191 value,
192 })
193 }
194
195 ConnectReplyKind::IncompatibleVersion => {
196 let value = deserializer.finish()?;
197
198 Ok(Self {
199 result: ConnectResult::IncompatibleVersion,
200 value,
201 })
202 }
203 }
204 }
205
206 fn value(&self) -> Option<&SerializedValueSlice> {
207 Some(&self.value)
208 }
209}
210
211impl Sealed for ConnectReply2 {}
212
213impl From<ConnectReply2> for Message {
214 fn from(msg: ConnectReply2) -> Self {
215 Self::ConnectReply2(msg)
216 }
217}
218
219#[cfg(test)]
220mod test {
221 use super::super::test::{assert_deserialize_eq_with_value, assert_serialize_eq};
222 use super::super::Message;
223 use super::{ConnectReply2, ConnectReplyData};
224
225 #[test]
226 fn ok() {
227 let serialized = [15, 0, 0, 0, 47, 4, 0, 0, 0, 39, 1, 0, 0, 0, 1];
228 let value = ConnectReplyData::new();
229
230 let msg = ConnectReply2::ok_with_serialize_data(1, &value).unwrap();
231 assert_serialize_eq(&msg, serialized);
232 assert_deserialize_eq_with_value(&msg, serialized, &value);
233
234 let msg = Message::ConnectReply2(msg);
235 assert_serialize_eq(&msg, serialized);
236 assert_deserialize_eq_with_value(&msg, serialized, &value);
237 }
238
239 #[test]
240 fn rejected() {
241 let serialized = [14, 0, 0, 0, 47, 4, 0, 0, 0, 39, 1, 0, 0, 1];
242 let value = ConnectReplyData::new();
243
244 let msg = ConnectReply2::rejected_with_serialize_data(&value).unwrap();
245 assert_serialize_eq(&msg, serialized);
246 assert_deserialize_eq_with_value(&msg, serialized, &value);
247
248 let msg = Message::ConnectReply2(msg);
249 assert_serialize_eq(&msg, serialized);
250 assert_deserialize_eq_with_value(&msg, serialized, &value);
251 }
252
253 #[test]
254 fn incompatible_version() {
255 let serialized = [14, 0, 0, 0, 47, 4, 0, 0, 0, 39, 1, 0, 0, 2];
256 let value = ConnectReplyData::new();
257
258 let msg = ConnectReply2::incompatible_version_with_serialize_data(&value).unwrap();
259 assert_serialize_eq(&msg, serialized);
260 assert_deserialize_eq_with_value(&msg, serialized, &value);
261
262 let msg = Message::ConnectReply2(msg);
263 assert_serialize_eq(&msg, serialized);
264 assert_deserialize_eq_with_value(&msg, serialized, &value);
265 }
266}