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