1use super::message_ops::Sealed;
2use super::{
3 Message, MessageDeserializeError, MessageKind, MessageOps, MessageSerializeError,
4 MessageSerializer, MessageWithValueDeserializer, OptionKind,
5};
6use crate::{SerializedValue, SerializedValueSlice, ServiceCookie};
7use bytes::BytesMut;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))]
11pub struct CallFunction2 {
12 pub serial: u32,
13 pub service_cookie: ServiceCookie,
14 pub function: u32,
15 pub version: Option<u32>,
16 pub value: SerializedValue,
17}
18
19impl MessageOps for CallFunction2 {
20 fn kind(&self) -> MessageKind {
21 MessageKind::CallFunction2
22 }
23
24 fn serialize_message(self) -> Result<BytesMut, MessageSerializeError> {
25 let mut serializer = MessageSerializer::with_value(self.value, MessageKind::CallFunction2)?;
26
27 serializer.put_varint_u32_le(self.serial);
28 serializer.put_uuid(self.service_cookie.0);
29 serializer.put_varint_u32_le(self.function);
30
31 match self.version {
32 None => {
33 serializer.put_discriminant_u8(OptionKind::None);
34 }
35
36 Some(version) => {
37 serializer.put_discriminant_u8(OptionKind::Some);
38 serializer.put_varint_u32_le(version);
39 }
40 }
41
42 serializer.finish()
43 }
44
45 fn deserialize_message(buf: BytesMut) -> Result<Self, MessageDeserializeError> {
46 let mut deserializer = MessageWithValueDeserializer::new(buf, MessageKind::CallFunction2)?;
47
48 let serial = deserializer.try_get_varint_u32_le()?;
49 let service_cookie = deserializer.try_get_uuid().map(ServiceCookie)?;
50 let function = deserializer.try_get_varint_u32_le()?;
51
52 let version = match deserializer.try_get_discriminant_u8()? {
53 OptionKind::None => None,
54 OptionKind::Some => deserializer.try_get_varint_u32_le().map(Some)?,
55 };
56
57 let value = deserializer.finish()?;
58
59 Ok(Self {
60 serial,
61 service_cookie,
62 function,
63 version,
64 value,
65 })
66 }
67
68 fn value(&self) -> Option<&SerializedValueSlice> {
69 Some(&self.value)
70 }
71
72 fn value_mut(&mut self) -> Option<&mut SerializedValue> {
73 Some(&mut self.value)
74 }
75}
76
77impl Sealed for CallFunction2 {}
78
79impl From<CallFunction2> for Message {
80 fn from(msg: CallFunction2) -> Self {
81 Self::CallFunction2(msg)
82 }
83}
84
85#[cfg(test)]
86mod test {
87 use super::super::test::{assert_deserialize_eq_with_value, assert_serialize_eq};
88 use super::super::Message;
89 use super::CallFunction2;
90 use crate::{tags, SerializedValue, ServiceCookie};
91 use uuid::uuid;
92
93 #[test]
94 fn call_function2_without_version() {
95 let serialized = [
96 30, 0, 0, 0, 62, 2, 0, 0, 0, 3, 4, 1, 0x02, 0x6c, 0x31, 0x42, 0x53, 0x0b, 0x4d, 0x65,
97 0x85, 0x0d, 0xa2, 0x97, 0xdc, 0xc2, 0xfe, 0xcb, 2, 0,
98 ];
99 let value = 4u8;
100
101 let msg = CallFunction2 {
102 serial: 1,
103 service_cookie: ServiceCookie(uuid!("026c3142-530b-4d65-850d-a297dcc2fecb")),
104 function: 2,
105 version: None,
106 value: SerializedValue::serialize(value).unwrap(),
107 };
108
109 assert_serialize_eq(&msg, serialized);
110 assert_deserialize_eq_with_value::<_, _, tags::U8, _>(&msg, serialized, &value);
111
112 let msg = Message::CallFunction2(msg);
113 assert_serialize_eq(&msg, serialized);
114 assert_deserialize_eq_with_value::<_, _, tags::U8, _>(&msg, serialized, &value);
115 }
116
117 #[test]
118 fn call_function2_with_version() {
119 let serialized = [
120 31, 0, 0, 0, 62, 2, 0, 0, 0, 3, 4, 1, 0x02, 0x6c, 0x31, 0x42, 0x53, 0x0b, 0x4d, 0x65,
121 0x85, 0x0d, 0xa2, 0x97, 0xdc, 0xc2, 0xfe, 0xcb, 2, 1, 3,
122 ];
123 let value = 4u8;
124
125 let msg = CallFunction2 {
126 serial: 1,
127 service_cookie: ServiceCookie(uuid!("026c3142-530b-4d65-850d-a297dcc2fecb")),
128 function: 2,
129 version: Some(3),
130 value: SerializedValue::serialize(value).unwrap(),
131 };
132
133 assert_serialize_eq(&msg, serialized);
134 assert_deserialize_eq_with_value::<_, _, tags::U8, _>(&msg, serialized, &value);
135
136 let msg = Message::CallFunction2(msg);
137 assert_serialize_eq(&msg, serialized);
138 assert_deserialize_eq_with_value::<_, _, tags::U8, _>(&msg, serialized, &value);
139 }
140}