someip_sd_wire/
packet.rs

1//! Packet module
2//!
3//! This module contains the `Packet` type, which is a read/write wrapper around a SOME/IP-SD packet buffer.
4
5use crate::error::Error;
6use crate::field;
7use byteorder::{ByteOrder, NetworkEndian};
8use core::fmt;
9
10/// Result type alias using the crate's Error type.
11#[allow(dead_code)]
12pub type Result<T> = core::result::Result<T, Error>;
13
14/// A read/write wrapper around a SOME/IP-SD packet buffer.
15///
16/// SOME/IP-SD message format:
17/// - Flags (1 byte)
18/// - Reserved (3 bytes)
19/// - Length of Entries Array (4 bytes)
20/// - Entries Array (variable)
21/// - Length of Options Array (4 bytes)
22/// - Options Array (variable)
23#[allow(dead_code)]
24#[derive(Debug, PartialEq, Eq, Clone)]
25pub struct Packet<T: AsRef<[u8]>> {
26    buffer: T,
27}
28
29#[allow(dead_code)]
30impl<T: AsRef<[u8]>> Packet<T> {
31    /// Creates a new unchecked `Packet`.
32    ///
33    /// # Arguments
34    ///
35    /// * `buffer` - A buffer containing the packet data.
36    ///
37    /// # Returns
38    ///
39    /// * `Packet` - A new `Packet` instance.
40    pub const fn new_unchecked(buffer: T) -> Packet<T> {
41        Packet { buffer }
42    }
43
44    /// Creates a new checked `Packet`.
45    ///
46    /// # Arguments
47    ///
48    /// * `buffer` - A buffer containing the packet data.
49    ///
50    /// # Returns
51    ///
52    /// * `Result<Packet>` - A new `Packet` instance if the buffer is valid.
53    pub fn new_checked(buffer: T) -> Result<Packet<T>> {
54        let packet = Self::new_unchecked(buffer);
55        packet.check_len()?;
56        Ok(packet)
57    }
58
59    /// Checks the length of the packet.
60    ///
61    /// # Returns
62    ///
63    /// * `Result<()>` - Ok if the length is valid, otherwise an error.
64    pub fn check_len(&self) -> Result<()> {
65        let len = self.buffer.as_ref().len();
66        if len < field::entries::MIN_HEADER_LEN {
67            return Err(Error::BufferTooShort);
68        }
69
70        // Check that the buffer is large enough for the declared entries and options
71        let entries_len = self.entries_length();
72        
73        // Need at least: up to and including OPTIONS_LENGTH field
74        let min_with_entries = field::entries::OPTIONS_LENGTH(entries_len).end;
75        if len < min_with_entries {
76            return Err(Error::BufferTooShort);
77        }
78        
79        let options_len = self.options_length();
80        
81        // Full length: everything including OPTIONS_ARRAY
82        let required_len = field::entries::OPTIONS_ARRAY(entries_len, options_len).end;
83        if len < required_len {
84            return Err(Error::BufferTooShort);
85        }
86
87        Ok(())
88    }
89
90    /// Returns the inner buffer.
91    ///
92    /// # Returns
93    ///
94    /// * `T` - The inner buffer.
95    pub fn into_inner(self) -> T {
96        self.buffer
97    }
98
99    /// Returns a reference to the inner buffer.
100    ///
101    /// # Returns
102    ///
103    /// * `&[u8]` - A reference to the buffer.
104    #[inline]
105    pub fn as_slice(&self) -> &[u8] {
106        self.buffer.as_ref()
107    }
108
109    /// Returns the Flags byte
110    ///
111    /// # Returns
112    ///
113    /// * `u8` - The Flags byte of the packet
114    pub fn flags(&self) -> u8 {
115        self.buffer.as_ref()[field::header::FLAGS.start]
116    }
117
118    /// Returns the Reserved field (3 bytes, should be 0x000000)
119    ///
120    /// # Returns
121    ///
122    /// * `u32` - The Reserved field (only uses lower 24 bits)
123    pub fn reserved(&self) -> u32 {
124        let bytes = &self.buffer.as_ref()[field::header::RESERVED];
125        // Read 3 bytes as u32 (big-endian)
126        ((bytes[0] as u32) << 16) | ((bytes[1] as u32) << 8) | (bytes[2] as u32)
127    }
128
129    /// Returns the Length of Entries Array (4 bytes)
130    ///
131    /// # Returns
132    ///
133    /// * `usize` - The length of the entries array in bytes
134    pub fn entries_length(&self) -> usize {
135        NetworkEndian::read_u32(&self.buffer.as_ref()[field::entries::LENGTH]) as usize
136    }
137
138    /// Returns the Entries Array
139    ///
140    /// # Returns
141    ///
142    /// * `&[u8]` - A slice containing the entries array
143    pub fn entries_array(&self) -> &[u8] {
144        let len = self.entries_length();
145        let range = field::entries::ENTRIES_ARRAY(len);
146        &self.buffer.as_ref()[range]
147    }
148
149    /// Returns the Length of Options Array (4 bytes)
150    ///
151    /// # Returns
152    ///
153    /// * `usize` - The length of the options array in bytes
154    pub fn options_length(&self) -> usize {
155        let entries_len = self.entries_length();
156        NetworkEndian::read_u32(&self.buffer.as_ref()[field::entries::OPTIONS_LENGTH(entries_len)]) as usize
157    }
158
159    /// Returns the Options Array
160    ///
161    /// # Returns
162    ///
163    /// * `&[u8]` - A slice containing the options array
164    pub fn options_array(&self) -> &[u8] {
165        let entries_len = self.entries_length();
166        let options_len = self.options_length();
167        &self.buffer.as_ref()[field::entries::OPTIONS_ARRAY(entries_len, options_len)]
168    }
169
170    /// Get the total packet length
171    ///
172    /// # Returns
173    ///
174    /// * `usize` - The total length of the packet
175    pub fn total_length(&self) -> usize {
176        let entries_len = self.entries_length();
177        let options_len = self.options_length();
178        field::entries::OPTIONS_ARRAY(entries_len, options_len).end
179    }
180}
181
182#[allow(dead_code)]
183impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
184    /// Sets the Flags byte
185    ///
186    /// # Arguments
187    ///
188    /// * `flags` - The flags byte to set
189    pub fn set_flags(&mut self, flags: u8) {
190        self.buffer.as_mut()[field::header::FLAGS.start] = flags;
191    }
192
193    /// Sets the Reserved field (3 bytes, should be 0x000000)
194    ///
195    /// # Arguments
196    ///
197    /// * `reserved` - The reserved value (only lower 24 bits used)
198    pub fn set_reserved(&mut self, reserved: u32) {
199        let bytes = &mut self.buffer.as_mut()[field::header::RESERVED];
200        bytes[0] = ((reserved >> 16) & 0xFF) as u8;
201        bytes[1] = ((reserved >> 8) & 0xFF) as u8;
202        bytes[2] = (reserved & 0xFF) as u8;
203    }
204
205    /// Sets the Length of Entries Array (4 bytes)
206    ///
207    /// # Arguments
208    ///
209    /// * `length` - The length of the entries array in bytes
210    pub fn set_entries_length(&mut self, length: u32) {
211        NetworkEndian::write_u32(&mut self.buffer.as_mut()[field::entries::LENGTH], length);
212    }
213
214    /// Returns a mutable slice to the Entries Array
215    ///
216    /// # Returns
217    ///
218    /// * `&mut [u8]` - A mutable slice to write entries data
219    pub fn entries_array_mut(&mut self) -> &mut [u8] {
220        let len = self.entries_length();
221        let range = field::entries::ENTRIES_ARRAY(len);
222        &mut self.buffer.as_mut()[range]
223    }
224
225    /// Sets the Length of Options Array (4 bytes)
226    ///
227    /// # Arguments
228    ///
229    /// * `length` - The length of the options array in bytes
230    pub fn set_options_length(&mut self, length: u32) {
231        let entries_len = self.entries_length();
232        NetworkEndian::write_u32(&mut self.buffer.as_mut()[field::entries::OPTIONS_LENGTH(entries_len)], length);
233    }
234
235    /// Returns a mutable slice to the Options Array
236    ///
237    /// # Returns
238    ///
239    /// * `&mut [u8]` - A mutable slice to write options data
240    pub fn options_array_mut(&mut self) -> &mut [u8] {
241        let entries_len = self.entries_length();
242        let options_len = self.options_length();
243        &mut self.buffer.as_mut()[field::entries::OPTIONS_ARRAY(entries_len, options_len)]
244    }
245}
246
247impl<T: AsRef<[u8]>> fmt::Display for Packet<T> {
248    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
249        write!(
250            f,
251            "SOME/IP-SD Packet: flags=0x{:02X}, entries_len={}, options_len={}",
252            self.flags(),
253            self.entries_length(),
254            self.options_length()
255        )
256    }
257}
258
259#[cfg(test)]
260mod tests {
261    use super::*;
262
263    #[test]
264    fn test_packet_new_unchecked() {
265        let buffer = [0u8; 12];
266        let packet = Packet::new_unchecked(&buffer[..]);
267        assert_eq!(packet.as_slice().len(), 12);
268    }
269
270    #[test]
271    fn test_packet_too_short() {
272        let buffer = [0u8; 8]; // Too small
273        let result = Packet::new_checked(&buffer[..]);
274        assert_eq!(result, Err(Error::BufferTooShort));
275    }
276
277    #[test]
278    fn test_packet_flags() {
279        let mut buffer = [0u8; 12];
280        let mut packet = Packet::new_unchecked(&mut buffer[..]);
281        packet.set_flags(0x80);
282        assert_eq!(packet.flags(), 0x80);
283    }
284
285    #[test]
286    fn test_packet_reserved() {
287        let mut buffer = [0u8; 12];
288        let mut packet = Packet::new_unchecked(&mut buffer[..]);
289        packet.set_reserved(0x123456);
290        assert_eq!(packet.reserved(), 0x123456);
291    }
292
293    #[test]
294    fn test_packet_entries_length() {
295        let mut buffer = [0u8; 20];
296        let mut packet = Packet::new_unchecked(&mut buffer[..]);
297        packet.set_entries_length(8);
298        assert_eq!(packet.entries_length(), 8);
299    }
300
301    #[test]
302    fn test_packet_with_entries_and_options() {
303        // Create a packet with 16 bytes of entries and 8 bytes of options
304        // Total: 12 header + 16 entries + 8 options = 36 bytes
305        let mut buffer = [0u8; 12 + 16 + 8];
306        let mut packet = Packet::new_unchecked(&mut buffer[..]);
307        
308        packet.set_flags(0x80);
309        packet.set_reserved(0);
310        packet.set_entries_length(16);
311        
312        // Fill entries with test data
313        {
314            let entries = packet.entries_array_mut();
315            for (i, byte) in entries.iter_mut().enumerate() {
316                *byte = i as u8;
317            }
318        }
319        
320        packet.set_options_length(8);
321        
322        // Fill options with test data
323        {
324            let options = packet.options_array_mut();
325            for (i, byte) in options.iter_mut().enumerate() {
326                *byte = (i + 100) as u8;
327            }
328        }
329        
330        assert_eq!(packet.flags(), 0x80);
331        assert_eq!(packet.entries_length(), 16);
332        assert_eq!(packet.options_length(), 8);
333        assert_eq!(packet.entries_array()[0], 0);
334        assert_eq!(packet.options_array()[0], 100);
335    }
336}