aldrin_core/message/
query_introspection_reply.rs

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