1use super::message_ops::Sealed;
2use super::{
3 Message, MessageDeserializeError, MessageKind, MessageOps, MessageSerializeError,
4 MessageSerializer, MessageWithValueDeserializer,
5};
6use crate::tags::{self, PrimaryTag, Tag};
7use crate::{
8 Deserialize, DeserializeError, DeserializePrimary, Deserializer, Serialize, SerializeError,
9 SerializePrimary, SerializedValue, SerializedValueSlice, Serializer,
10};
11use bytes::BytesMut;
12use num_enum::{IntoPrimitive, TryFromPrimitive};
13
14#[derive(Debug, Clone, PartialEq, Eq, Default)]
15#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))]
16pub struct ConnectReplyData {
17 pub user: Option<SerializedValue>,
18}
19
20impl ConnectReplyData {
21 pub fn new() -> Self {
22 Self::default()
23 }
24
25 pub fn serialize_user_as<T: Tag>(
26 &mut self,
27 user: impl Serialize<T>,
28 ) -> Result<&mut Self, SerializeError> {
29 self.user = SerializedValue::serialize_as(user).map(Some)?;
30 Ok(self)
31 }
32
33 pub fn serialize_user(
34 &mut self,
35 user: impl SerializePrimary,
36 ) -> Result<&mut Self, SerializeError> {
37 self.serialize_user_as(user)
38 }
39
40 pub fn deserialize_user_as<T: Tag, U: Deserialize<T>>(
41 &self,
42 ) -> Option<Result<U, DeserializeError>> {
43 self.user
44 .as_deref()
45 .map(SerializedValueSlice::deserialize_as)
46 }
47
48 pub fn deserialize_user<T: DeserializePrimary>(&self) -> Option<Result<T, DeserializeError>> {
49 self.deserialize_user_as()
50 }
51}
52
53impl Tag for ConnectReplyData {}
54
55impl PrimaryTag for ConnectReplyData {
56 type Tag = Self;
57}
58
59#[derive(IntoPrimitive, TryFromPrimitive)]
60#[repr(u32)]
61enum ConnectReplyDataField {
62 User = 0,
63}
64
65impl Serialize<Self> for ConnectReplyData {
66 fn serialize(self, serializer: Serializer) -> Result<(), SerializeError> {
67 serializer.serialize(&self)
68 }
69}
70
71impl Serialize<ConnectReplyData> for &ConnectReplyData {
72 fn serialize(self, serializer: Serializer) -> Result<(), SerializeError> {
73 let mut serializer = serializer.serialize_struct2()?;
74
75 serializer.serialize_if_some::<tags::Option<tags::Value>>(
76 ConnectReplyDataField::User,
77 &self.user,
78 )?;
79
80 serializer.finish()
81 }
82}
83
84impl Deserialize<Self> for ConnectReplyData {
85 fn deserialize(deserializer: Deserializer) -> Result<Self, DeserializeError> {
86 let mut deserializer = deserializer.deserialize_struct()?;
87
88 let mut user = None;
89
90 while let Some(deserializer) = deserializer.deserialize()? {
91 match deserializer.try_id() {
92 Ok(ConnectReplyDataField::User) => user = deserializer.deserialize()?,
93 Err(_) => deserializer.skip()?,
94 }
95 }
96
97 deserializer.finish(Self { user })
98 }
99}
100
101#[derive(Debug, Copy, Clone, PartialEq, Eq, IntoPrimitive, TryFromPrimitive)]
102#[repr(u8)]
103enum ConnectReplyKind {
104 Ok = 0,
105 Rejected = 1,
106 IncompatibleVersion = 2,
107}
108
109#[derive(Debug, Copy, Clone, PartialEq, Eq)]
110#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))]
111pub enum ConnectResult {
112 Ok(u32),
113 Rejected,
114 IncompatibleVersion,
115}
116
117#[derive(Debug, Clone, PartialEq, Eq)]
118#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))]
119pub struct ConnectReply2 {
120 pub result: ConnectResult,
121 pub value: SerializedValue,
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 fn value_mut(&mut self) -> Option<&mut SerializedValue> {
190 Some(&mut self.value)
191 }
192}
193
194impl Sealed for ConnectReply2 {}
195
196impl From<ConnectReply2> for Message {
197 fn from(msg: ConnectReply2) -> Self {
198 Self::ConnectReply2(msg)
199 }
200}
201
202#[cfg(test)]
203mod test {
204 use super::super::test::{assert_deserialize_eq_with_value, assert_serialize_eq};
205 use super::super::Message;
206 use super::{ConnectReply2, ConnectReplyData, ConnectResult};
207 use crate::SerializedValue;
208
209 #[test]
210 fn ok() {
211 let serialized = [13, 0, 0, 0, 47, 2, 0, 0, 0, 65, 0, 0, 1];
212 let value = ConnectReplyData::new();
213
214 let msg = ConnectReply2 {
215 result: ConnectResult::Ok(1),
216 value: SerializedValue::serialize(&value).unwrap(),
217 };
218 assert_serialize_eq(&msg, serialized);
219 assert_deserialize_eq_with_value(&msg, serialized, &value);
220
221 let msg = Message::ConnectReply2(msg);
222 assert_serialize_eq(&msg, serialized);
223 assert_deserialize_eq_with_value(&msg, serialized, &value);
224 }
225
226 #[test]
227 fn rejected() {
228 let serialized = [12, 0, 0, 0, 47, 2, 0, 0, 0, 65, 0, 1];
229 let value = ConnectReplyData::new();
230
231 let msg = ConnectReply2 {
232 result: ConnectResult::Rejected,
233 value: SerializedValue::serialize(&value).unwrap(),
234 };
235 assert_serialize_eq(&msg, serialized);
236 assert_deserialize_eq_with_value(&msg, serialized, &value);
237
238 let msg = Message::ConnectReply2(msg);
239 assert_serialize_eq(&msg, serialized);
240 assert_deserialize_eq_with_value(&msg, serialized, &value);
241 }
242
243 #[test]
244 fn incompatible_version() {
245 let serialized = [12, 0, 0, 0, 47, 2, 0, 0, 0, 65, 0, 2];
246 let value = ConnectReplyData::new();
247
248 let msg = ConnectReply2 {
249 result: ConnectResult::IncompatibleVersion,
250 value: SerializedValue::serialize(&value).unwrap(),
251 };
252 assert_serialize_eq(&msg, serialized);
253 assert_deserialize_eq_with_value(&msg, serialized, &value);
254
255 let msg = Message::ConnectReply2(msg);
256 assert_serialize_eq(&msg, serialized);
257 assert_deserialize_eq_with_value(&msg, serialized, &value);
258 }
259}