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