rsomeip_proto/interface.rs
1//! SOME/IP service interface.
2
3use crate::{InterfaceVersion, Message, MessageType, MethodId, ReturnCode};
4use std::collections::HashMap;
5
6/// SOME/IP service interface.
7///
8/// An interface defines a series of methods which determine the types of messages that it can send or
9/// receive. These methods can differ between successive versions of the interface.
10///
11/// This struct is used to manage the state of a service interface by defining its methods, and
12/// checking incoming and outgoing messages for correctness.
13///
14/// # Stub vs Proxy
15///
16/// An interface can behave either as a stub which serves methods to be "called", or as a proxy which
17/// "calls" these methods. This determines what kind of message types the interface considers valid
18/// for a given method type.
19#[derive(Debug, Default, Clone, PartialEq, Eq)]
20pub struct Interface {
21 /// Major version of the service interface.
22 pub version: InterfaceVersion,
23 /// Whether the interface should behave as a stub or proxy.
24 pub flavor: InterfaceType,
25 /// Methods registered with the interface.
26 pub methods: HashMap<MethodId, MethodType>,
27}
28
29impl Interface {
30 /// Returns `self` as a [`Stub`].
31 ///
32 /// # Examples
33 ///
34 /// ```rust
35 /// use rsomeip_proto::{Interface, InterfaceType};
36 ///
37 /// let interface = Interface::default().into_stub();
38 /// assert_eq!(interface.flavor, InterfaceType::Stub);
39 /// ```
40 ///
41 /// [`Stub`]: InterfaceType::Stub
42 #[inline]
43 #[must_use]
44 pub const fn into_stub(mut self) -> Self {
45 self.flavor = InterfaceType::Stub;
46 self
47 }
48
49 /// Returns `self` as a [`Proxy`].
50 ///
51 /// # Examples
52 ///
53 /// ```rust
54 /// use rsomeip_proto::{Interface, InterfaceType};
55 ///
56 /// let interface = Interface::default().into_proxy();
57 /// assert_eq!(interface.flavor, InterfaceType::Proxy);
58 /// ```
59 ///
60 /// [`Proxy`]: InterfaceType::Proxy
61 #[inline]
62 #[must_use]
63 pub const fn into_proxy(mut self) -> Self {
64 self.flavor = InterfaceType::Proxy;
65 self
66 }
67
68 /// Returns `self` with the given [`InterfaceVersion`].
69 ///
70 /// # Examples
71 ///
72 /// ```rust
73 /// use rsomeip_proto::{Interface, InterfaceVersion};
74 ///
75 /// let interface = Interface::default().with_version(InterfaceVersion::new(1));
76 /// assert_eq!(interface.version, InterfaceVersion::new(1));
77 /// ```
78 #[inline]
79 #[must_use]
80 pub const fn with_version(mut self, version: InterfaceVersion) -> Self {
81 self.version = version;
82 self
83 }
84
85 /// Returns `self` with the given method.
86 ///
87 /// This is the same as inserting a method with [`MethodType::Method`].
88 ///
89 /// # Examples
90 ///
91 /// ```rust
92 /// use rsomeip_proto::{Interface, MethodId, MethodType};
93 ///
94 /// let interface = Interface::default().with_method(MethodId::new(1));
95 /// assert_eq!(interface.get(MethodId::new(1)), Some(MethodType::Method));
96 /// ```
97 #[inline]
98 #[must_use]
99 pub fn with_method(mut self, id: MethodId) -> Self {
100 _ = self.insert(id, MethodType::Method);
101 self
102 }
103
104 /// Returns `self` with the given procedure.
105 ///
106 /// This is the same as inserting a method with [`MethodType::Procedure`].
107 ///
108 /// # Examples
109 ///
110 /// ```rust
111 /// use rsomeip_proto::{Interface, MethodId, MethodType};
112 ///
113 /// let interface = Interface::default().with_procedure(MethodId::new(1));
114 /// assert_eq!(interface.get(MethodId::new(1)), Some(MethodType::Procedure));
115 /// ```
116 #[inline]
117 #[must_use]
118 pub fn with_procedure(mut self, id: MethodId) -> Self {
119 _ = self.insert(id, MethodType::Procedure);
120 self
121 }
122
123 /// Returns `self` with the given event.
124 ///
125 /// This is the same as inserting a method with [`MethodType::Event`].
126 ///
127 /// # Examples
128 ///
129 /// ```rust
130 /// use rsomeip_proto::{Interface, MethodId, MethodType};
131 ///
132 /// let interface = Interface::default().with_event(MethodId::new(1));
133 /// assert_eq!(interface.get(MethodId::new(1)), Some(MethodType::Event));
134 /// ```
135 #[inline]
136 #[must_use]
137 pub fn with_event(mut self, id: MethodId) -> Self {
138 _ = self.insert(id, MethodType::Event);
139 self
140 }
141
142 /// Inserts a method with the given `id` and `flavor`.
143 ///
144 /// Returns the previous flavor.
145 ///
146 /// # Examples
147 ///
148 /// ```rust
149 /// use rsomeip_proto::{Interface, MethodId, MethodType};
150 ///
151 /// let mut interface = Interface::default();
152 /// assert_eq!(interface.insert(MethodId::new(1), MethodType::Method), None);
153 /// assert_eq!(interface.insert(MethodId::new(1), MethodType::Procedure), Some(MethodType::Method));
154 /// ```
155 #[inline]
156 pub fn insert(&mut self, id: MethodId, flavor: MethodType) -> Option<MethodType> {
157 self.methods.insert(id, flavor)
158 }
159
160 /// Removes the method with the given `id`.
161 ///
162 /// # Examples
163 ///
164 /// ```rust
165 /// use rsomeip_proto::{Interface, MethodId, MethodType};
166 ///
167 /// let mut interface = Interface::default().with_method(MethodId::new(1));
168 /// assert_eq!(interface.remove(MethodId::new(1)), Some(MethodType::Method));
169 /// assert_eq!(interface.remove(MethodId::new(1)), None);
170 /// ```
171 #[inline]
172 pub fn remove(&mut self, id: MethodId) -> Option<MethodType> {
173 self.methods.remove(&id)
174 }
175
176 /// Returns the flavor of the method with the given `id`.
177 ///
178 /// # Examples
179 ///
180 /// ```rust
181 /// use rsomeip_proto::{Interface, MethodId, MethodType};
182 ///
183 /// let interface = Interface::default().with_method(MethodId::new(1));
184 /// assert_eq!(interface.get(MethodId::new(1)), Some(MethodType::Method));
185 /// ```
186 #[inline]
187 #[must_use]
188 pub fn get(&self, id: MethodId) -> Option<MethodType> {
189 self.methods.get(&id).copied()
190 }
191
192 /// Returns a mutable reference to the method with the given `id`.
193 ///
194 /// # Examples
195 ///
196 /// ```rust
197 /// use rsomeip_proto::{Interface, MethodId, MethodType};
198 ///
199 /// let mut interface = Interface::default().with_method(MethodId::new(1));
200 /// assert_eq!(interface.get_mut(MethodId::new(1)), Some(&mut MethodType::Method));
201 /// ```
202 #[inline]
203 #[must_use]
204 pub fn get_mut(&mut self, id: MethodId) -> Option<&mut MethodType> {
205 self.methods.get_mut(&id)
206 }
207}
208
209/// Shorthand for making an error message.
210macro_rules! drop {
211 ($reason:expr) => {
212 Err((MessageError::Dropped($reason)))
213 };
214}
215
216/// Shorthand for making an error message.
217macro_rules! invalid {
218 ($reason:expr) => {
219 Err((MessageError::Invalid($reason)))
220 };
221}
222
223/// Shorthand for making an error message.
224macro_rules! invalid_or_dropped {
225 ($message_type:expr, $reason:expr) => {
226 Err((MessageError::invalid_or_dropped($message_type, $reason)))
227 };
228}
229
230impl Interface {
231 /// Checks if the `message` is valid in the given `direction`.
232 ///
233 /// This is used to confirm that the message parameters are correctly configured for this
234 /// interface when sending ([`Direction::Outgoing`]) or receiving it ([`Direction::Incoming`]).
235 ///
236 /// # Errors
237 ///
238 /// Returns a [`MessageError`] if the message is invalid.
239 pub(crate) fn check<T>(
240 &self,
241 message: &Message<T>,
242 direction: Direction,
243 ) -> Result<(), MessageError> {
244 // Check if interface version is correct.
245 if message.interface() != self.version {
246 return invalid_or_dropped!(message.message_type(), ReturnCode::WrongInterfaceVersion);
247 }
248
249 // Check if the method is registered.
250 let Some(method) = self.methods.get(&message.method) else {
251 return invalid_or_dropped!(message.message_type(), ReturnCode::UnknownMethod);
252 };
253
254 // Check if the message type is correct.
255 match direction {
256 Direction::Incoming => match (self.flavor, method) {
257 (InterfaceType::Stub, MethodType::Procedure) => {
258 if message.message_type() != MessageType::RequestNoReturn {
259 return drop!(ReturnCode::WrongMessageType);
260 }
261 }
262 (InterfaceType::Stub, MethodType::Method) => {
263 if message.message_type() != MessageType::Request {
264 return invalid!(ReturnCode::WrongMessageType);
265 }
266 }
267 (InterfaceType::Proxy, MethodType::Method) => {
268 if !matches!(
269 message.message_type(),
270 MessageType::Response | MessageType::Error
271 ) {
272 return drop!(ReturnCode::WrongMessageType);
273 }
274 }
275 (InterfaceType::Proxy, MethodType::Event) => {
276 if message.message_type() != MessageType::Notification {
277 return drop!(ReturnCode::WrongMessageType);
278 }
279 }
280 _ => return drop!(ReturnCode::WrongMessageType),
281 },
282 Direction::Outgoing => match (self.flavor, method) {
283 (InterfaceType::Stub, MethodType::Method) => {
284 if !matches!(
285 message.message_type(),
286 MessageType::Response | MessageType::Error
287 ) {
288 return invalid!(ReturnCode::WrongMessageType);
289 }
290 }
291 (InterfaceType::Stub, MethodType::Event) => {
292 if message.message_type() != MessageType::Notification {
293 return invalid!(ReturnCode::WrongMessageType);
294 }
295 }
296 (InterfaceType::Proxy, MethodType::Procedure) => {
297 if message.message_type() != MessageType::RequestNoReturn {
298 return invalid!(ReturnCode::WrongMessageType);
299 }
300 }
301 (InterfaceType::Proxy, MethodType::Method) => {
302 if message.message_type() != MessageType::Request {
303 return invalid!(ReturnCode::WrongMessageType);
304 }
305 }
306 _ => return invalid!(ReturnCode::WrongMessageType),
307 },
308 }
309 Ok(())
310 }
311}
312
313/// The type of a SOME/IP service interface.
314///
315/// This defines how it should process SOME/IP messages.
316#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
317pub enum InterfaceType {
318 /// A service interface being served on a local endpoint.
319 #[default]
320 Stub,
321 /// A service interface being served on a remote endpoint.
322 Proxy,
323}
324
325/// The type of a SOME/IP method.
326///
327/// This defines how it should process SOME/IP messages.
328#[derive(Debug, Clone, Copy, PartialEq, Eq)]
329pub enum MethodType {
330 /// A callable function on a service interface that does not return a value.
331 Procedure,
332 /// A callable function on a service interface that returns a value.
333 Method,
334 /// A non-callable event on the service interface.
335 Event,
336}
337
338/// The direction an event is taking through the endpoint.
339#[derive(Debug, Clone, Copy, PartialEq, Eq)]
340pub enum Direction {
341 /// The event is coming from a remote endpoint.
342 Incoming,
343 /// The event is going to a remote endpoint.
344 Outgoing,
345}
346
347/// A message processing error.
348///
349/// A SOME/IP endpoint may occasionally try to send or receive messages which are incorrectly
350/// configured for the service interface that processes them.
351///
352/// This enum serves as a way to represent the reason for a message to not be processed, as well as
353/// whether the error should be reported to the user or not.
354///
355/// # Error Handling
356///
357/// Depending on the error variant, either an error response should be sent back to the source or the
358/// whole message should be dropped.
359///
360/// If the error is [`MessageError::Invalid`], then an error response should be sent with the
361/// contained [`ReturnCode`]. Otherwise, the message should be dropped.
362#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
363pub enum MessageError {
364 #[error("invalid message: {0}")]
365 Invalid(ReturnCode),
366 #[error("message dropped: {0}")]
367 Dropped(ReturnCode),
368}
369
370impl MessageError {
371 /// Creates a new [`MessageError::Invalid`] or [`MessageError::Dropped`] depending on the
372 /// [`MessageType`].
373 ///
374 /// This is used to reduce the verbosity of having to specify whether a message should be
375 /// responded to or dropped in case of an error.
376 fn invalid_or_dropped(message_type: MessageType, return_code: ReturnCode) -> Self {
377 if message_type == MessageType::Request {
378 Self::Invalid(return_code)
379 } else {
380 Self::Dropped(return_code)
381 }
382 }
383}
384
385#[cfg(test)]
386mod tests {
387 use super::*;
388
389 /// A SOME/IP message.
390 type Message = crate::Message<rsomeip_bytes::Bytes>;
391
392 #[test]
393 fn interface_version_is_checked() {
394 // Create a new interface with a specific version.
395 let interface = Interface::default().with_version(InterfaceVersion::new(1));
396
397 // Check incoming and outgoing messages.
398 for value in [
399 MessageType::Request,
400 MessageType::Response,
401 MessageType::RequestNoReturn,
402 MessageType::Error,
403 MessageType::Notification,
404 MessageType::Unknown(0xff),
405 ] {
406 // Requests should not be dropped.
407 if value == MessageType::Request {
408 assert_eq!(
409 interface.check(
410 &Message::default().with_message_type(value),
411 Direction::Incoming
412 ),
413 invalid!(ReturnCode::WrongInterfaceVersion)
414 );
415 assert_eq!(
416 interface.check(
417 &Message::default().with_message_type(value),
418 Direction::Outgoing
419 ),
420 invalid!(ReturnCode::WrongInterfaceVersion)
421 );
422 } else {
423 assert_eq!(
424 interface.check(
425 &Message::default().with_message_type(value),
426 Direction::Incoming
427 ),
428 drop!(ReturnCode::WrongInterfaceVersion)
429 );
430 assert_eq!(
431 interface.check(
432 &Message::default().with_message_type(value),
433 Direction::Outgoing
434 ),
435 drop!(ReturnCode::WrongInterfaceVersion)
436 );
437 }
438 }
439 }
440
441 #[test]
442 fn method_id_is_checked() {
443 // Create a new interface without any methods.
444 let interface = Interface::default();
445
446 // Check incoming and outgoing messages.
447 for value in [
448 MessageType::Request,
449 MessageType::Response,
450 MessageType::RequestNoReturn,
451 MessageType::Error,
452 MessageType::Notification,
453 MessageType::Unknown(0xff),
454 ] {
455 // Requests should not be dropped.
456 if value == MessageType::Request {
457 assert_eq!(
458 interface.check(
459 &Message::default().with_message_type(value),
460 Direction::Incoming
461 ),
462 invalid!(ReturnCode::UnknownMethod)
463 );
464 assert_eq!(
465 interface.check(
466 &Message::default().with_message_type(value),
467 Direction::Outgoing
468 ),
469 invalid!(ReturnCode::UnknownMethod)
470 );
471 } else {
472 assert_eq!(
473 interface.check(
474 &Message::default().with_message_type(value),
475 Direction::Incoming
476 ),
477 drop!(ReturnCode::UnknownMethod)
478 );
479 assert_eq!(
480 interface.check(
481 &Message::default().with_message_type(value),
482 Direction::Outgoing
483 ),
484 drop!(ReturnCode::UnknownMethod)
485 );
486 }
487 }
488 }
489
490 #[test]
491 fn stub_method_valid_message_types() {
492 // Create a service interface stub.
493 let interface = Interface::default().with_method(MethodId::default());
494
495 // Check incoming messages.
496 assert_eq!(
497 interface.check(&Message::default(), Direction::Incoming),
498 Ok(())
499 );
500
501 // Check outgoing messages.
502 for value in [MessageType::Response, MessageType::Error] {
503 assert_eq!(
504 interface.check(
505 &Message::default().with_message_type(value),
506 Direction::Outgoing
507 ),
508 Ok(())
509 );
510 }
511 }
512
513 #[test]
514 fn stub_method_invalid_message_types() {
515 // Create a service interface stub.
516 let interface = Interface::default().with_method(MethodId::default());
517
518 // Check incoming messages.
519 for value in [
520 MessageType::Error,
521 MessageType::Notification,
522 MessageType::RequestNoReturn,
523 MessageType::Response,
524 MessageType::Unknown(0xff),
525 ] {
526 assert_eq!(
527 interface.check(
528 &Message::default().with_message_type(value),
529 Direction::Incoming
530 ),
531 invalid!(ReturnCode::WrongMessageType)
532 );
533 }
534
535 // Check outgoing messages.
536 for value in [
537 MessageType::Request,
538 MessageType::Notification,
539 MessageType::RequestNoReturn,
540 MessageType::Unknown(0xff),
541 ] {
542 assert_eq!(
543 interface.check(
544 &Message::default().with_message_type(value),
545 Direction::Outgoing
546 ),
547 invalid!(ReturnCode::WrongMessageType)
548 );
549 }
550 }
551
552 #[test]
553 fn stub_procedure_valid_message_types() {
554 // Create a service interface stub.
555 let interface = Interface::default().with_procedure(MethodId::default());
556
557 // Check incoming messages.
558 assert_eq!(
559 interface.check(
560 &Message::default().with_message_type(MessageType::RequestNoReturn),
561 Direction::Incoming
562 ),
563 Ok(())
564 );
565 }
566
567 #[test]
568 fn stub_procedure_invalid_message_types() {
569 // Create a service interface stub.
570 let interface = Interface::default().with_procedure(MethodId::default());
571
572 // Check incoming messages.
573 for value in [
574 MessageType::Error,
575 MessageType::Notification,
576 MessageType::Request,
577 MessageType::Response,
578 MessageType::Unknown(0xff),
579 ] {
580 assert_eq!(
581 interface.check(
582 &Message::default().with_message_type(value),
583 Direction::Incoming
584 ),
585 drop!(ReturnCode::WrongMessageType)
586 );
587 }
588
589 // Check outgoing messages.
590 for value in [
591 MessageType::Error,
592 MessageType::Notification,
593 MessageType::Request,
594 MessageType::RequestNoReturn,
595 MessageType::Response,
596 MessageType::Unknown(0xff),
597 ] {
598 assert_eq!(
599 interface.check(
600 &Message::default().with_message_type(value),
601 Direction::Outgoing
602 ),
603 invalid!(ReturnCode::WrongMessageType)
604 );
605 }
606 }
607
608 #[test]
609 fn stub_event_valid_message_types() {
610 // Create a service interface stub.
611 let interface = Interface::default().with_event(MethodId::default());
612
613 // Check outgoing messages.
614 assert_eq!(
615 interface.check(
616 &Message::default().with_message_type(MessageType::Notification),
617 Direction::Outgoing
618 ),
619 Ok(())
620 );
621 }
622
623 #[test]
624 fn stub_event_only_handles_notifications() {
625 // Create a service interface stub.
626 let interface = Interface::default().with_event(MethodId::default());
627
628 // Check incoming messages.
629 for value in [
630 MessageType::Error,
631 MessageType::Notification,
632 MessageType::Request,
633 MessageType::RequestNoReturn,
634 MessageType::Response,
635 MessageType::Unknown(0xff),
636 ] {
637 assert_eq!(
638 interface.check(
639 &Message::default().with_message_type(value),
640 Direction::Incoming
641 ),
642 drop!(ReturnCode::WrongMessageType)
643 );
644 }
645
646 // Check outgoing messages.
647 for value in [
648 MessageType::Error,
649 MessageType::Request,
650 MessageType::RequestNoReturn,
651 MessageType::Response,
652 MessageType::Unknown(0xff),
653 ] {
654 assert_eq!(
655 interface.check(
656 &Message::default().with_message_type(value),
657 Direction::Outgoing
658 ),
659 invalid!(ReturnCode::WrongMessageType)
660 );
661 }
662 }
663
664 #[test]
665 fn proxy_method_valid_message_types() {
666 // Create a service interface proxy.
667 let interface = Interface::default()
668 .with_method(MethodId::default())
669 .into_proxy();
670
671 // Check incoming messages.
672 for value in [MessageType::Response, MessageType::Error] {
673 assert_eq!(
674 interface.check(
675 &Message::default().with_message_type(value),
676 Direction::Incoming
677 ),
678 Ok(())
679 );
680 }
681
682 // Check outgoing messages.
683 assert_eq!(
684 interface.check(
685 &Message::default().with_message_type(MessageType::Request),
686 Direction::Outgoing
687 ),
688 Ok(())
689 );
690 }
691
692 #[test]
693 fn proxy_method_invalid_message_types() {
694 // Create a service interface proxy.
695 let interface = Interface::default()
696 .with_method(MethodId::default())
697 .into_proxy();
698
699 // Check incoming messages.
700 for value in [
701 MessageType::Request,
702 MessageType::Notification,
703 MessageType::RequestNoReturn,
704 MessageType::Unknown(0xff),
705 ] {
706 assert_eq!(
707 interface.check(
708 &Message::default().with_message_type(value),
709 Direction::Incoming
710 ),
711 drop!(ReturnCode::WrongMessageType)
712 );
713 }
714
715 // Check outgoing messages.
716 for value in [
717 MessageType::Response,
718 MessageType::Error,
719 MessageType::Notification,
720 MessageType::RequestNoReturn,
721 MessageType::Unknown(0xff),
722 ] {
723 assert_eq!(
724 interface.check(
725 &Message::default().with_message_type(value),
726 Direction::Outgoing
727 ),
728 invalid!(ReturnCode::WrongMessageType)
729 );
730 }
731 }
732
733 #[test]
734 fn proxy_procedure_valid_message_types() {
735 // Create a service interface proxy.
736 let interface = Interface::default()
737 .with_procedure(MethodId::default())
738 .into_proxy();
739
740 // Check outgoing messages.
741 assert_eq!(
742 interface.check(
743 &Message::default().with_message_type(MessageType::RequestNoReturn),
744 Direction::Outgoing
745 ),
746 Ok(())
747 );
748 }
749
750 #[test]
751 fn proxy_procedure_invalid_message_types() {
752 // Create a service interface proxy.
753 let interface = Interface::default()
754 .with_procedure(MethodId::default())
755 .into_proxy();
756
757 // Check incoming messages.
758 for value in [
759 MessageType::Error,
760 MessageType::Notification,
761 MessageType::Request,
762 MessageType::RequestNoReturn,
763 MessageType::Response,
764 MessageType::Unknown(0xff),
765 ] {
766 assert_eq!(
767 interface.check(
768 &Message::default().with_message_type(value),
769 Direction::Incoming
770 ),
771 drop!(ReturnCode::WrongMessageType)
772 );
773 }
774
775 // Check outgoing messages.
776 for value in [
777 MessageType::Error,
778 MessageType::Notification,
779 MessageType::Request,
780 MessageType::Response,
781 MessageType::Unknown(0xff),
782 ] {
783 assert_eq!(
784 interface.check(
785 &Message::default().with_message_type(value),
786 Direction::Outgoing
787 ),
788 invalid!(ReturnCode::WrongMessageType)
789 );
790 }
791 }
792
793 #[test]
794 fn proxy_event_valid_message_types() {
795 // Create a service interface proxy.
796 let interface = Interface::default()
797 .with_event(MethodId::default())
798 .into_proxy();
799
800 // Check incoming messages.
801 assert_eq!(
802 interface.check(
803 &Message::default().with_message_type(MessageType::Notification),
804 Direction::Incoming
805 ),
806 Ok(())
807 );
808 }
809
810 #[test]
811 fn proxy_event_invalid_message_types() {
812 // Create a service interface proxy.
813 let interface = Interface::default()
814 .with_event(MethodId::default())
815 .into_proxy();
816
817 // Check incoming messages.
818 for value in [
819 MessageType::Error,
820 MessageType::Request,
821 MessageType::RequestNoReturn,
822 MessageType::Response,
823 MessageType::Unknown(0xff),
824 ] {
825 assert_eq!(
826 interface.check(
827 &Message::default().with_message_type(value),
828 Direction::Incoming
829 ),
830 drop!(ReturnCode::WrongMessageType)
831 );
832 }
833
834 // Check outgoing messages.
835 for value in [
836 MessageType::Error,
837 MessageType::Request,
838 MessageType::RequestNoReturn,
839 MessageType::Notification,
840 MessageType::Response,
841 MessageType::Unknown(0xff),
842 ] {
843 assert_eq!(
844 interface.check(
845 &Message::default().with_message_type(value),
846 Direction::Outgoing
847 ),
848 invalid!(ReturnCode::WrongMessageType)
849 );
850 }
851 }
852}