aldrin_core/message/
query_service_info_reply.rs

1use super::message_ops::Sealed;
2use super::{Message, MessageKind, MessageOps};
3use crate::error::SerializeError;
4use crate::message_deserializer::{MessageDeserializeError, MessageWithValueDeserializer};
5use crate::message_serializer::{MessageSerializeError, MessageSerializer};
6use crate::serialized_value::{SerializedValue, SerializedValueSlice};
7use crate::service_info::ServiceInfo;
8use bytes::BytesMut;
9use num_enum::{IntoPrimitive, TryFromPrimitive};
10
11#[derive(Debug, Copy, Clone, PartialEq, Eq, IntoPrimitive, TryFromPrimitive)]
12#[repr(u8)]
13enum QueryServiceInfoReplyKind {
14    Ok = 0,
15    InvalidService = 1,
16}
17
18#[derive(Debug, Clone, PartialEq, Eq)]
19#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))]
20pub enum QueryServiceInfoResult {
21    Ok(SerializedValue),
22    InvalidService,
23}
24
25impl QueryServiceInfoResult {
26    pub fn ok_with_serialize_info(info: ServiceInfo) -> Result<Self, SerializeError> {
27        SerializedValue::serialize(&info).map(Self::Ok)
28    }
29}
30
31#[derive(Debug, Clone, PartialEq, Eq)]
32#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))]
33pub struct QueryServiceInfoReply {
34    pub serial: u32,
35    pub result: QueryServiceInfoResult,
36}
37
38impl QueryServiceInfoReply {
39    pub fn ok_with_serialize_info(serial: u32, info: ServiceInfo) -> Result<Self, SerializeError> {
40        let result = QueryServiceInfoResult::ok_with_serialize_info(info)?;
41        Ok(Self { serial, result })
42    }
43}
44
45impl MessageOps for QueryServiceInfoReply {
46    fn kind(&self) -> MessageKind {
47        MessageKind::QueryServiceInfoReply
48    }
49
50    fn serialize_message(self) -> Result<BytesMut, MessageSerializeError> {
51        let serializer = match self.result {
52            QueryServiceInfoResult::Ok(value) => {
53                let mut serializer =
54                    MessageSerializer::with_value(value, MessageKind::QueryServiceInfoReply)?;
55
56                serializer.put_varint_u32_le(self.serial);
57                serializer.put_discriminant_u8(QueryServiceInfoReplyKind::Ok);
58
59                serializer
60            }
61
62            QueryServiceInfoResult::InvalidService => {
63                let mut serializer =
64                    MessageSerializer::with_none_value(MessageKind::QueryServiceInfoReply);
65
66                serializer.put_varint_u32_le(self.serial);
67                serializer.put_discriminant_u8(QueryServiceInfoReplyKind::InvalidService);
68
69                serializer
70            }
71        };
72
73        serializer.finish()
74    }
75
76    fn deserialize_message(buf: BytesMut) -> Result<Self, MessageDeserializeError> {
77        let mut deserializer =
78            MessageWithValueDeserializer::new(buf, MessageKind::QueryServiceInfoReply)?;
79
80        let serial = deserializer.try_get_varint_u32_le()?;
81
82        match deserializer.try_get_discriminant_u8()? {
83            QueryServiceInfoReplyKind::Ok => {
84                let value = deserializer.finish()?;
85
86                Ok(Self {
87                    serial,
88                    result: QueryServiceInfoResult::Ok(value),
89                })
90            }
91
92            QueryServiceInfoReplyKind::InvalidService => {
93                deserializer.finish_discard_value()?;
94
95                Ok(Self {
96                    serial,
97                    result: QueryServiceInfoResult::InvalidService,
98                })
99            }
100        }
101    }
102
103    fn value(&self) -> Option<&SerializedValueSlice> {
104        match self.result {
105            QueryServiceInfoResult::Ok(ref value) => Some(value),
106            QueryServiceInfoResult::InvalidService => None,
107        }
108    }
109}
110
111impl Sealed for QueryServiceInfoReply {}
112
113impl From<QueryServiceInfoReply> for Message {
114    fn from(msg: QueryServiceInfoReply) -> Self {
115        Self::QueryServiceInfoReply(msg)
116    }
117}
118
119#[cfg(test)]
120mod test {
121    use super::super::test::{
122        assert_deserialize_eq, assert_deserialize_eq_with_value, assert_serialize_eq,
123    };
124    use super::super::Message;
125    use super::{QueryServiceInfoReply, QueryServiceInfoResult};
126    use crate::ids::TypeId;
127    use crate::service_info::ServiceInfo;
128    use uuid::uuid;
129
130    #[test]
131    fn ok() {
132        let serialized = [
133            39, 0, 0, 0, 54, 28, 0, 0, 0, 39, 3, 0, 7, 2, 1, 1, 14, 0xcf, 0x41, 0xc6, 0x88, 0x49,
134            0x76, 0x46, 0xa5, 0x8e, 0x2d, 0x48, 0x71, 0x02, 0x58, 0xbc, 0x2c, 2, 1, 2, 1, 1, 0,
135        ];
136        let info = ServiceInfo::new(2)
137            .set_type_id(TypeId(uuid!("cf41c688-4976-46a5-8e2d-48710258bc2c")))
138            .set_subscribe_all(true);
139
140        let msg = QueryServiceInfoReply::ok_with_serialize_info(1, info).unwrap();
141        assert_serialize_eq(&msg, serialized);
142        assert_deserialize_eq_with_value(&msg, serialized, &info);
143
144        let msg = Message::QueryServiceInfoReply(msg);
145        assert_serialize_eq(&msg, serialized);
146        assert_deserialize_eq_with_value(&msg, serialized, &info);
147    }
148
149    #[test]
150    fn invalid_service() {
151        let serialized = [12, 0, 0, 0, 54, 1, 0, 0, 0, 0, 1, 1];
152
153        let msg = QueryServiceInfoReply {
154            serial: 1,
155            result: QueryServiceInfoResult::InvalidService,
156        };
157        assert_serialize_eq(&msg, serialized);
158        assert_deserialize_eq(&msg, serialized);
159
160        let msg = Message::QueryServiceInfoReply(msg);
161        assert_serialize_eq(&msg, serialized);
162        assert_deserialize_eq(&msg, serialized);
163    }
164}