aldrin_core/message/
connect_reply2.rs

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}