someip_wire/
packet.rs

1//! Packet module
2//!
3//! This module contains the `Packet` type, which is a read/write wrapper around a Some/IP packet buffer.
4
5use crate::error::Error;
6use crate::field;
7use crate::types::{MessageId, RequestId};
8use byteorder::{ByteOrder, NetworkEndian};
9use core::fmt;
10
11#[allow(dead_code)]
12pub type Result<T> = core::result::Result<T, Error>;
13
14/// A read/write wrapper around a Some/IP packet buffer.
15#[allow(dead_code)]
16#[derive(Debug, PartialEq, Eq, Clone)]
17pub struct Packet<T: AsRef<[u8]>> {
18    buffer: T,
19}
20
21#[allow(dead_code)]
22impl<T: AsRef<[u8]>> Packet<T> {
23    /// Creates a new unchecked `Packet`.
24    ///
25    /// # Arguments
26    ///
27    /// * `buffer` - A buffer containing the packet data.
28    ///
29    /// # Returns
30    ///
31    /// * `Packet` - A new `Packet` instance.
32    pub const fn new_unchecked(buffer: T) -> Packet<T> {
33        Packet { buffer }
34    }
35
36    /// Creates a new checked `Packet`.
37    ///
38    /// # Arguments
39    ///
40    /// * `buffer` - A buffer containing the packet data.
41    ///
42    /// # Returns
43    ///
44    /// * `Result<Packet>` - A new `Packet` instance if the buffer is valid.
45    pub fn new_checked(buffer: T) -> Result<Packet<T>> {
46        let packet = Self::new_unchecked(buffer);
47        match packet.check_len() {
48            Ok(_) => Ok(packet),
49            Err(_) => Err(Error),
50        }
51    }
52
53    /// Checks the length of the packet.
54    ///
55    /// # Returns
56    ///
57    /// * `Result<()>` - Ok if the length is valid, otherwise an error.
58    pub fn check_len(&self) -> Result<()> {
59        let len = self.buffer.as_ref().len();
60        if len < field::header::HEADER_LENGTH {
61            Err(Error)
62        } else {
63            Ok(())
64        }
65    }
66
67    /// Returns the inner buffer.
68    ///
69    /// # Returns
70    ///
71    /// * `T` - The inner buffer.
72    pub fn into_inner(self) -> T {
73        self.buffer
74    }
75
76    /// Returns a reference to the inner buffer.
77    ///
78    /// # Returns
79    ///
80    /// * `&[u8]` - A reference to the buffer.
81    #[inline]
82    pub fn as_slice(&self) -> &[u8] {
83        self.buffer.as_ref()
84    }
85
86    /// Returns the Message ID
87    ///
88    /// # Returns
89    ///
90    /// * `MessageId` - The Message ID of the packet
91    pub fn message_id(&self) -> MessageId {
92        let raw_id = NetworkEndian::read_u32(&self.buffer.as_ref()[field::header::MESSAGE_ID]);
93        MessageId::from_u32(raw_id)
94    }
95
96    /// Returns the Payload Length
97    ///
98    /// # Returns
99    ///
100    /// * `usize` - The Payload Length of the packet
101    pub fn payload_length(&self) -> usize {
102        NetworkEndian::read_u32(&self.buffer.as_ref()[field::header::LENGTH]) as usize
103    }
104
105    /// Returns the Request ID
106    ///
107    /// # Returns
108    ///
109    /// * `u32` - The Request ID of the packet
110    pub fn request_id(&self) -> RequestId {
111        RequestId::from_u32(NetworkEndian::read_u32(
112            &self.buffer.as_ref()[field::header::REQUEST_ID],
113        ))
114    }
115
116    /// Returns the Protocol Version
117    ///
118    /// # Returns
119    ///
120    /// * `u8` - The Protocol Version of the packet
121    pub fn protocol_version(&self) -> u8 {
122        self.buffer.as_ref()[field::header::PROTOCOL_VERSION.start]
123    }
124
125    /// Returns the Interface Version
126    ///
127    /// # Returns
128    ///
129    /// * `u8` - The Interface Version of the packet
130    pub fn interface_version(&self) -> u8 {
131        self.buffer.as_ref()[field::header::INTERFACE_VERSION.start]
132    }
133
134    /// Returns the Message Type (raw u8)
135    ///
136    /// # Returns
137    ///
138    /// * `u8` - The raw message type byte from the packet
139    pub fn message_type(&self) -> u8 {
140        self.buffer.as_ref()[field::header::MESSAGE_TYPE.start]
141    }
142
143    /// Returns the Return Code (raw u8)
144    ///
145    /// # Returns
146    ///
147    /// * `u8` - The raw return code byte from the packet
148    pub fn return_code(&self) -> u8 {
149        self.buffer.as_ref()[field::header::RETURN_CODE.start]
150    }
151
152    /// Returns the range of the payload data
153    ///
154    /// # Returns
155    ///
156    /// * `Range<usize>` - The range of the payload data.
157    pub fn payload_data_range(&self) -> core::ops::Range<usize> {
158        let payload_len = self.payload_length().saturating_sub(8); // Subtract 8 header bytes from SOME/IP length field
159        field::header::RETURN_CODE.end..field::header::RETURN_CODE.end + payload_len as usize
160    }
161
162    /// Returns the length of the payload data.
163    ///
164    /// # Returns
165    ///
166    /// * `usize` - The length of the payload data.
167    pub fn payload_data_length(&self) -> usize {
168        self.payload_length().saturating_sub(8) as usize // Subtract 8 header bytes from SOME/IP length field
169    }
170}
171
172#[allow(dead_code)]
173impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
174    /// Sets the Message ID
175    ///
176    /// # Arguments
177    ///
178    /// * `message_id` - The new Message ID to set
179    pub fn set_message_id(&mut self, message_id: MessageId) {
180        let raw_id = message_id.to_u32();
181        NetworkEndian::write_u32(&mut self.buffer.as_mut()[field::header::MESSAGE_ID], raw_id);
182    }
183
184    /// Sets the Payload Length
185    ///
186    /// # Arguments
187    ///
188    /// * `length` - The new Payload Length to set
189    pub fn set_payload_length(&mut self, length: u32) {
190        NetworkEndian::write_u32(
191            &mut self.buffer.as_mut()[field::header::LENGTH],
192            length,
193        );
194    }
195
196    /// Sets the Request ID
197    ///
198    /// # Arguments
199    ///
200    /// * `request_id` - The new Request ID to set
201    pub fn set_request_id(&mut self, request_id: RequestId) {
202        let raw_id = request_id.to_u32();
203        NetworkEndian::write_u32(&mut self.buffer.as_mut()[field::header::REQUEST_ID], raw_id);
204    }
205
206    /// Sets the Protocol Version
207    ///
208    /// # Arguments
209    ///
210    /// * `version` - The new Protocol Version to set
211    pub fn set_protocol_version(&mut self, version: u8) {
212        self.buffer.as_mut()[field::header::PROTOCOL_VERSION.start] = version;
213    }
214
215    /// Sets the Interface Version
216    ///
217    /// # Arguments
218    ///
219    /// * `version` - The new Interface Version to set
220    pub fn set_interface_version(&mut self, version: u8) {
221        self.buffer.as_mut()[field::header::INTERFACE_VERSION.start] = version;
222    }
223
224    /// Sets the Message Type (raw u8)
225    ///
226    /// # Arguments
227    ///
228    /// * `message_type` - The new message type byte to set
229    pub fn set_message_type(&mut self, message_type: u8) {
230        self.buffer.as_mut()[field::header::MESSAGE_TYPE.start] = message_type;
231    }
232
233    /// Sets the Return Code (raw u8)
234    ///
235    /// # Arguments
236    ///
237    /// * `return_code` - The new return code byte to set
238    pub fn set_return_code(&mut self, return_code: u8) {
239        self.buffer.as_mut()[field::header::RETURN_CODE.start] = return_code;
240    }
241}
242
243#[allow(dead_code)]
244impl<'a, T: AsRef<[u8]> + ?Sized> Packet<&'a T> {
245    /// Returns a reference to the payload data,
246    ///
247    /// # Returns
248    ///
249    /// * `&'a [u8]` - A reference to the payload data.
250    #[inline]
251    pub fn payload_data(&self) -> &'a [u8] {
252        let payload_range = self.payload_data_range();
253        &self.buffer.as_ref()[payload_range]
254    }
255
256    /// Returns a reference to the entire message.
257    ///
258    /// # Returns
259    ///
260    /// * `&'a [u8]` - A reference to the entire message.
261    #[inline]
262    pub fn entire_message(&self) -> &'a [u8] {
263        let data = self.buffer.as_ref();
264        let total_length = field::header::HEADER_LENGTH + self.payload_data_length();
265        &data[..total_length]
266    }
267}
268
269#[allow(dead_code)]
270impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> Packet<&'a mut T> {
271    /// Returns a mutable reference to the payload data,
272    ///
273    /// # Returns
274    ///
275    /// * `&'a mut [u8]` - A mutable reference to the payload data.
276    #[inline]
277    pub fn payload_data_mut(&mut self) -> &mut [u8] {
278        let payload_range = self.payload_data_range();
279        &mut self.buffer.as_mut()[payload_range]
280    }
281
282    /// Returns a mutable reference to the entire message.
283    ///
284    /// # Returns
285    ///
286    /// * `&'a mut [u8]` - A mutable reference to the entire message.
287    #[inline]
288    pub fn entire_message_mut(&mut self) -> &mut [u8] {
289        let payload_length = self.payload_data_length();
290        let data = self.buffer.as_mut();
291        let total_length = field::header::HEADER_LENGTH + payload_length;
292        &mut data[..total_length]
293    }
294}
295
296impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> {
297    /// Formats the packet as a string
298    ///
299    /// # Arguments
300    ///
301    /// * `f` - The formatter
302    ///
303    /// # Returns
304    ///
305    /// * `fmt::Result` - The result of the formatting
306    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
307        write!(
308            f,
309            "Some/IP Packet: message_id={}, length={}, request_id={}, protocol_version={}, interface_version={}, message_type=0x{:02X}, return_code=0x{:02X}",
310            self.message_id(),
311            self.payload_length(),
312            self.request_id(),
313            self.protocol_version(),
314            self.interface_version(),
315            self.message_type(),
316            self.return_code()
317        )?;
318
319        Ok(())
320    }
321}