Skip to main content

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}