simple_someip/traits.rs
1#[cfg(feature = "std")]
2use crate::protocol::sd;
3use crate::protocol::{self, MessageId, sd::Flags};
4
5/// Information about a service endpoint extracted from an SD message.
6#[cfg(feature = "std")]
7pub struct OfferedEndpoint {
8 /// The SOME/IP service ID.
9 pub service_id: u16,
10 /// The SOME/IP instance ID.
11 pub instance_id: u16,
12 /// The major version of the offered service interface.
13 pub major_version: u8,
14 /// The minor version of the offered service interface.
15 pub minor_version: u32,
16 /// The IPv4 socket address extracted from the SD options, if present.
17 pub addr: Option<std::net::SocketAddrV4>,
18 /// `true` for `OfferService`, `false` for `StopOfferService`.
19 pub is_offer: bool,
20}
21
22/// A trait for types that can be serialized to a [`Writer`](embedded_io::Write).
23///
24/// `WireFormat` acts as the base trait for all types that can be serialized
25/// as part of the Simple SOME/IP ecosystem. Decoding is handled by zero-copy
26/// view types (`HeaderView`, `MessageView`, etc.) instead of this trait.
27pub trait WireFormat: Send + Sized + Sync {
28 /// Returns the number of bytes required to serialize this value.
29 fn required_size(&self) -> usize;
30
31 /// Serialize a value to a byte stream.
32 /// Returns the number of bytes written.
33 /// # Errors
34 /// - If the data cannot be written to the stream
35 fn encode<T: embedded_io::Write>(&self, writer: &mut T) -> Result<usize, protocol::Error>;
36
37 /// Encode into a byte slice, returning the number of bytes written.
38 ///
39 /// # Errors
40 /// Returns an error if `buf` is too small (requires at least
41 /// [`required_size()`](Self::required_size) bytes).
42 fn encode_to_slice(&self, buf: &mut [u8]) -> Result<usize, protocol::Error> {
43 self.encode(&mut &mut *buf)
44 }
45
46 /// Encode into a newly allocated `Vec<u8>`.
47 ///
48 /// # Errors
49 /// Returns an error if encoding fails.
50 #[cfg(feature = "std")]
51 fn encode_to_vec(&self) -> Result<std::vec::Vec<u8>, protocol::Error> {
52 let mut buf = std::vec![0u8; self.required_size()];
53 self.encode_to_slice(&mut buf)?;
54 Ok(buf)
55 }
56}
57
58/// A trait for SOME/IP Payload types that can be serialized to a
59/// [`Writer`](embedded_io::Write) and constructed from raw payload bytes.
60///
61/// Note that SOME/IP payloads are not self identifying, so the [Message ID](protocol::MessageId)
62/// must be provided by the caller.
63pub trait PayloadWireFormat: core::fmt::Debug + Send + Sized + Sync {
64 /// The SD header type used by this payload implementation.
65 type SdHeader: WireFormat + Clone + core::fmt::Debug + Eq;
66
67 /// Get the Message ID for the payload
68 fn message_id(&self) -> MessageId;
69 /// Get the payload as a service discovery header
70 fn as_sd_header(&self) -> Option<&Self::SdHeader>;
71 /// Construct a payload from raw bytes and a message ID.
72 /// # Errors
73 /// - If the message ID is not supported
74 /// - If the payload bytes cannot be parsed
75 fn from_payload_bytes(message_id: MessageId, payload: &[u8]) -> Result<Self, protocol::Error>;
76 /// Create a `PayloadWireFormat` from a service discovery [Header](protocol::sd::Header)
77 fn new_sd_payload(header: &Self::SdHeader) -> Self;
78 /// Return the SD flags if this payload is a service discovery message.
79 fn sd_flags(&self) -> Option<Flags>;
80 /// Number of bytes required to write the payload
81 fn required_size(&self) -> usize;
82 /// Serialize the payload to a [Writer](embedded_io::Write)
83 ///
84 /// # Errors
85 ///
86 /// Returns an error if the payload cannot be written to the writer.
87 fn encode<T: embedded_io::Write>(&self, writer: &mut T) -> Result<usize, protocol::Error>;
88
89 /// Construct an SD header for subscribing to an event group.
90 #[cfg(feature = "std")]
91 #[allow(clippy::too_many_arguments)]
92 fn new_subscription_sd_header(
93 service_id: u16,
94 instance_id: u16,
95 major_version: u8,
96 ttl: u32,
97 event_group_id: u16,
98 client_ip: std::net::Ipv4Addr,
99 protocol: sd::TransportProtocol,
100 client_port: u16,
101 ) -> Self::SdHeader;
102
103 /// Extract offered/stopped service endpoints from this SD payload.
104 ///
105 /// Default implementation returns an empty vec. Concrete implementations
106 /// that have access to SD entries and options should override this.
107 #[cfg(feature = "std")]
108 fn offered_endpoints(&self) -> std::vec::Vec<OfferedEndpoint> {
109 std::vec::Vec::new()
110 }
111
112 /// Return `(service_id, instance_id)` pairs for every SD entry in this
113 /// payload, regardless of entry type.
114 ///
115 /// Used for per-service-instance session/reboot tracking so that all SD
116 /// traffic (not just offers) contributes to reboot detection.
117 #[cfg(feature = "std")]
118 fn service_instances(&self) -> std::vec::Vec<(u16, u16)> {
119 std::vec::Vec::new()
120 }
121}