aldrin_core/message/
call_function2.rs

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}