Skip to main content

simple_someip/protocol/
byte_order.rs

1use crate::protocol::Error;
2use embedded_io::Error as _;
3
4/// Extension trait for reading big-endian values from a byte stream.
5///
6/// The only required method is [`read_bytes`](ReadBytesExt::read_bytes).
7/// Backed by `embedded_io::Read` via a blanket impl.
8pub trait ReadBytesExt {
9    /// Read exactly `buf.len()` bytes from the stream.
10    ///
11    /// # Errors
12    /// Returns [`Error::Io`] if the underlying reader fails.
13    fn read_bytes(&mut self, buf: &mut [u8]) -> Result<(), Error>;
14
15    /// Read a single `u8`.
16    ///
17    /// # Errors
18    /// Returns [`Error::Io`] if the underlying reader fails.
19    fn read_u8(&mut self) -> Result<u8, Error> {
20        let mut buf = [0u8; 1];
21        self.read_bytes(&mut buf)?;
22        Ok(buf[0])
23    }
24
25    /// Read an `i8`.
26    ///
27    /// # Errors
28    /// Returns [`Error::Io`] if the underlying reader fails.
29    fn read_i8(&mut self) -> Result<i8, Error> {
30        self.read_u8().map(u8::cast_signed)
31    }
32
33    /// Read a `u16` in big-endian byte order.
34    ///
35    /// # Errors
36    /// Returns [`Error::Io`] if the underlying reader fails.
37    fn read_u16_be(&mut self) -> Result<u16, Error> {
38        let mut buf = [0u8; 2];
39        self.read_bytes(&mut buf)?;
40        Ok(u16::from_be_bytes(buf))
41    }
42
43    /// Read an `i16` in big-endian byte order.
44    ///
45    /// # Errors
46    /// Returns [`Error::Io`] if the underlying reader fails.
47    fn read_i16_be(&mut self) -> Result<i16, Error> {
48        let mut buf = [0u8; 2];
49        self.read_bytes(&mut buf)?;
50        Ok(i16::from_be_bytes(buf))
51    }
52
53    /// Read the next 3 bytes as the lower 3 bytes of a `u32` in big-endian byte order.
54    ///
55    /// # Errors
56    /// Returns [`Error::Io`] if the underlying reader fails.
57    fn read_u24_be(&mut self) -> Result<u32, Error> {
58        let mut buf = [0u8; 3];
59        self.read_bytes(&mut buf)?;
60        Ok(u32::from_be_bytes([0, buf[0], buf[1], buf[2]]))
61    }
62
63    /// Read a `u32` in big-endian byte order.
64    ///
65    /// # Errors
66    /// Returns [`Error::Io`] if the underlying reader fails.
67    fn read_u32_be(&mut self) -> Result<u32, Error> {
68        let mut buf = [0u8; 4];
69        self.read_bytes(&mut buf)?;
70        Ok(u32::from_be_bytes(buf))
71    }
72
73    /// Read an `i32` in big-endian byte order.
74    ///
75    /// # Errors
76    /// Returns [`Error::Io`] if the underlying reader fails.
77    fn read_i32_be(&mut self) -> Result<i32, Error> {
78        let mut buf = [0u8; 4];
79        self.read_bytes(&mut buf)?;
80        Ok(i32::from_be_bytes(buf))
81    }
82
83    /// Read a `u64` in big-endian byte order.
84    ///
85    /// # Errors
86    /// Returns [`Error::Io`] if the underlying reader fails.
87    fn read_u64_be(&mut self) -> Result<u64, Error> {
88        let mut buf = [0u8; 8];
89        self.read_bytes(&mut buf)?;
90        Ok(u64::from_be_bytes(buf))
91    }
92
93    /// Read an `i64` in big-endian byte order.
94    ///
95    /// # Errors
96    /// Returns [`Error::Io`] if the underlying reader fails.
97    fn read_i64_be(&mut self) -> Result<i64, Error> {
98        let mut buf = [0u8; 8];
99        self.read_bytes(&mut buf)?;
100        Ok(i64::from_be_bytes(buf))
101    }
102
103    /// Read a `u128` in big-endian byte order.
104    ///
105    /// # Errors
106    /// Returns [`Error::Io`] if the underlying reader fails.
107    fn read_u128_be(&mut self) -> Result<u128, Error> {
108        let mut buf = [0u8; 16];
109        self.read_bytes(&mut buf)?;
110        Ok(u128::from_be_bytes(buf))
111    }
112
113    /// Read an `i128` in big-endian byte order.
114    ///
115    /// # Errors
116    /// Returns [`Error::Io`] if the underlying reader fails.
117    fn read_i128_be(&mut self) -> Result<i128, Error> {
118        let mut buf = [0u8; 16];
119        self.read_bytes(&mut buf)?;
120        Ok(i128::from_be_bytes(buf))
121    }
122
123    /// Read an `f32` in big-endian byte order.
124    ///
125    /// # Errors
126    /// Returns [`Error::Io`] if the underlying reader fails.
127    fn read_f32_be(&mut self) -> Result<f32, Error> {
128        let mut buf = [0u8; 4];
129        self.read_bytes(&mut buf)?;
130        Ok(f32::from_be_bytes(buf))
131    }
132
133    /// Read an `f64` in big-endian byte order.
134    ///
135    /// # Errors
136    /// Returns [`Error::Io`] if the underlying reader fails.
137    fn read_f64_be(&mut self) -> Result<f64, Error> {
138        let mut buf = [0u8; 8];
139        self.read_bytes(&mut buf)?;
140        Ok(f64::from_be_bytes(buf))
141    }
142}
143
144impl<T: embedded_io::Read> ReadBytesExt for T {
145    fn read_bytes(&mut self, buf: &mut [u8]) -> Result<(), Error> {
146        self.read_exact(buf).map_err(|e| match e {
147            embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other),
148            embedded_io::ReadExactError::Other(e) => Error::Io(e.kind()),
149        })
150    }
151}
152
153/// Extension trait for writing big-endian values to a byte stream.
154///
155/// The only required method is [`write_bytes`](WriteBytesExt::write_bytes).
156/// Backed by `embedded_io::Write` via a blanket impl.
157pub trait WriteBytesExt {
158    /// Write all bytes from `buf` to the stream.
159    ///
160    /// # Errors
161    /// Returns [`Error::Io`] if the underlying writer fails.
162    fn write_bytes(&mut self, buf: &[u8]) -> Result<(), Error>;
163
164    /// Write a single `u8`.
165    ///
166    /// # Errors
167    /// Returns [`Error::Io`] if the underlying writer fails.
168    fn write_u8(&mut self, val: u8) -> Result<(), Error> {
169        self.write_bytes(&[val])
170    }
171
172    /// Write an `i8`.
173    ///
174    /// # Errors
175    /// Returns [`Error::Io`] if the underlying writer fails.
176    fn write_i8(&mut self, val: i8) -> Result<(), Error> {
177        self.write_bytes(&[val.cast_unsigned()])
178    }
179
180    /// Write a `u16` in big-endian byte order.
181    ///
182    /// # Errors
183    /// Returns [`Error::Io`] if the underlying writer fails.
184    fn write_u16_be(&mut self, val: u16) -> Result<(), Error> {
185        self.write_bytes(&val.to_be_bytes())
186    }
187
188    /// Write an `i16` in big-endian byte order.
189    ///
190    /// # Errors
191    /// Returns [`Error::Io`] if the underlying writer fails.
192    fn write_i16_be(&mut self, val: i16) -> Result<(), Error> {
193        self.write_bytes(&val.to_be_bytes())
194    }
195
196    /// Write the lower 3 bytes of a `u32` in big-endian byte order.
197    ///
198    /// # Errors
199    /// Returns [`Error::Io`] if the underlying writer fails.
200    fn write_u24_be(&mut self, val: u32) -> Result<(), Error> {
201        self.write_bytes(&val.to_be_bytes()[1..])
202    }
203
204    /// Write a `u32` in big-endian byte order.
205    ///
206    /// # Errors
207    /// Returns [`Error::Io`] if the underlying writer fails.
208    fn write_u32_be(&mut self, val: u32) -> Result<(), Error> {
209        self.write_bytes(&val.to_be_bytes())
210    }
211
212    /// Write an `i32` in big-endian byte order.
213    ///
214    /// # Errors
215    /// Returns [`Error::Io`] if the underlying writer fails.
216    fn write_i32_be(&mut self, val: i32) -> Result<(), Error> {
217        self.write_bytes(&val.to_be_bytes())
218    }
219
220    /// Write a `u64` in big-endian byte order.
221    ///
222    /// # Errors
223    /// Returns [`Error::Io`] if the underlying writer fails.
224    fn write_u64_be(&mut self, val: u64) -> Result<(), Error> {
225        self.write_bytes(&val.to_be_bytes())
226    }
227
228    /// Write an `i64` in big-endian byte order.
229    ///
230    /// # Errors
231    /// Returns [`Error::Io`] if the underlying writer fails.
232    fn write_i64_be(&mut self, val: i64) -> Result<(), Error> {
233        self.write_bytes(&val.to_be_bytes())
234    }
235
236    /// Write a `u128` in big-endian byte order.
237    ///
238    /// # Errors
239    /// Returns [`Error::Io`] if the underlying writer fails.
240    fn write_u128_be(&mut self, val: u128) -> Result<(), Error> {
241        self.write_bytes(&val.to_be_bytes())
242    }
243
244    /// Write an `i128` in big-endian byte order.
245    ///
246    /// # Errors
247    /// Returns [`Error::Io`] if the underlying writer fails.
248    fn write_i128_be(&mut self, val: i128) -> Result<(), Error> {
249        self.write_bytes(&val.to_be_bytes())
250    }
251
252    /// Write an `f32` in big-endian byte order.
253    ///
254    /// # Errors
255    /// Returns [`Error::Io`] if the underlying writer fails.
256    fn write_f32_be(&mut self, val: f32) -> Result<(), Error> {
257        self.write_bytes(&val.to_be_bytes())
258    }
259
260    /// Write an `f64` in big-endian byte order.
261    ///
262    /// # Errors
263    /// Returns [`Error::Io`] if the underlying writer fails.
264    fn write_f64_be(&mut self, val: f64) -> Result<(), Error> {
265        self.write_bytes(&val.to_be_bytes())
266    }
267}
268
269impl<T: embedded_io::Write> WriteBytesExt for T {
270    fn write_bytes(&mut self, buf: &[u8]) -> Result<(), Error> {
271        self.write_all(buf).map_err(|e| Error::Io(e.kind()))
272    }
273}
274
275#[cfg(test)]
276// Strict float equality is correct here: these tests verify byte-level
277// round-tripping of `to_be_bytes` / `read_f*_be`, where the result must
278// be bitwise-identical to the input.
279#[allow(clippy::float_cmp)]
280mod tests {
281    use super::*;
282
283    struct FailingWriter;
284
285    impl embedded_io::ErrorType for FailingWriter {
286        type Error = embedded_io::ErrorKind;
287    }
288
289    impl embedded_io::Write for FailingWriter {
290        fn write(&mut self, _buf: &[u8]) -> Result<usize, Self::Error> {
291            Err(embedded_io::ErrorKind::BrokenPipe)
292        }
293
294        fn flush(&mut self) -> Result<(), Self::Error> {
295            Ok(())
296        }
297    }
298
299    struct FailingReader;
300
301    impl embedded_io::ErrorType for FailingReader {
302        type Error = embedded_io::ErrorKind;
303    }
304
305    impl embedded_io::Read for FailingReader {
306        fn read(&mut self, _buf: &mut [u8]) -> Result<usize, Self::Error> {
307            Err(embedded_io::ErrorKind::BrokenPipe)
308        }
309    }
310
311    // --- Error mapping ---
312
313    #[test]
314    fn write_io_error_maps_to_error_io() {
315        assert!(matches!(
316            FailingWriter.write_u8(0),
317            Err(Error::Io(embedded_io::ErrorKind::BrokenPipe))
318        ));
319    }
320
321    #[test]
322    fn read_io_error_maps_to_error_io() {
323        assert!(matches!(
324            FailingReader.read_u8(),
325            Err(Error::Io(embedded_io::ErrorKind::BrokenPipe))
326        ));
327    }
328
329    // --- ReadBytesExt ---
330
331    #[test]
332    fn read_u8_decodes_correctly() {
333        let buf: &[u8] = &[0xAB];
334        assert_eq!((&mut &*buf).read_u8().unwrap(), 0xAB);
335    }
336
337    #[test]
338    fn read_i8_decodes_correctly() {
339        let buf: &[u8] = &[0xFF];
340        assert_eq!((&mut &*buf).read_i8().unwrap(), -1);
341    }
342
343    #[test]
344    fn read_u16_be_decodes_correctly() {
345        let buf: &[u8] = &[0x01, 0x02];
346        assert_eq!((&mut &*buf).read_u16_be().unwrap(), 0x0102);
347    }
348
349    #[test]
350    fn read_i16_be_decodes_correctly() {
351        let buf: &[u8] = &[0xFF, 0xFE];
352        assert_eq!((&mut &*buf).read_i16_be().unwrap(), -2);
353    }
354
355    #[test]
356    fn read_u24_be_decodes_correctly() {
357        let buf: &[u8] = &[0x01, 0x02, 0x03];
358        assert_eq!((&mut &*buf).read_u24_be().unwrap(), 0x0001_0203);
359    }
360
361    #[test]
362    fn read_u32_be_decodes_correctly() {
363        let buf: &[u8] = &[0x01, 0x02, 0x03, 0x04];
364        assert_eq!((&mut &*buf).read_u32_be().unwrap(), 0x0102_0304);
365    }
366
367    #[test]
368    fn read_i32_be_decodes_correctly() {
369        let buf: &[u8] = &[0xFF, 0xFF, 0xFF, 0xFE];
370        assert_eq!((&mut &*buf).read_i32_be().unwrap(), -2);
371    }
372
373    #[test]
374    fn read_u64_be_decodes_correctly() {
375        let buf: &[u8] = &[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
376        assert_eq!((&mut &*buf).read_u64_be().unwrap(), 0x0102_0304_0506_0708);
377    }
378
379    #[test]
380    fn read_i64_be_decodes_correctly() {
381        let buf: &[u8] = &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE];
382        assert_eq!((&mut &*buf).read_i64_be().unwrap(), -2);
383    }
384
385    #[test]
386    fn read_u128_be_decodes_correctly() {
387        let buf: &[u8] = &[
388            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
389            0x00, 0x01,
390        ];
391        assert_eq!((&mut &*buf).read_u128_be().unwrap(), 1);
392    }
393
394    #[test]
395    fn read_i128_be_decodes_correctly() {
396        let buf: &[u8] = &[
397            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
398            0xFF, 0xFE,
399        ];
400        assert_eq!((&mut &*buf).read_i128_be().unwrap(), -2);
401    }
402
403    #[test]
404    fn read_f32_be_decodes_correctly() {
405        let expected: f32 = 1.0;
406        let buf = expected.to_be_bytes();
407        assert_eq!((&mut buf.as_slice()).read_f32_be().unwrap(), expected);
408    }
409
410    #[test]
411    fn read_f64_be_decodes_correctly() {
412        let expected: f64 = 1.0;
413        let buf = expected.to_be_bytes();
414        assert_eq!((&mut buf.as_slice()).read_f64_be().unwrap(), expected);
415    }
416
417    // --- WriteBytesExt ---
418
419    #[test]
420    fn write_u8_encodes_correctly() {
421        let mut buf = [0u8; 1];
422        buf.as_mut_slice().write_u8(0xAB).unwrap();
423        assert_eq!(buf, [0xAB]);
424    }
425
426    #[test]
427    fn write_i8_encodes_correctly() {
428        let mut buf = [0u8; 1];
429        buf.as_mut_slice().write_i8(-1).unwrap();
430        assert_eq!(buf, [0xFF]);
431    }
432
433    #[test]
434    fn write_u16_be_encodes_correctly() {
435        let mut buf = [0u8; 2];
436        buf.as_mut_slice().write_u16_be(0x0102).unwrap();
437        assert_eq!(buf, [0x01, 0x02]);
438    }
439
440    #[test]
441    fn write_i16_be_encodes_correctly() {
442        let mut buf = [0u8; 2];
443        buf.as_mut_slice().write_i16_be(-2).unwrap();
444        assert_eq!(buf, [0xFF, 0xFE]);
445    }
446
447    #[test]
448    fn write_u24_be_encodes_correctly() {
449        let mut buf = [0u8; 3];
450        buf.as_mut_slice().write_u24_be(0x0001_0203).unwrap();
451        assert_eq!(buf, [0x01, 0x02, 0x03]);
452    }
453
454    #[test]
455    fn write_u32_be_encodes_correctly() {
456        let mut buf = [0u8; 4];
457        buf.as_mut_slice().write_u32_be(0x0102_0304).unwrap();
458        assert_eq!(buf, [0x01, 0x02, 0x03, 0x04]);
459    }
460
461    #[test]
462    fn write_i32_be_encodes_correctly() {
463        let mut buf = [0u8; 4];
464        buf.as_mut_slice().write_i32_be(-2).unwrap();
465        assert_eq!(buf, [0xFF, 0xFF, 0xFF, 0xFE]);
466    }
467
468    #[test]
469    fn write_u64_be_encodes_correctly() {
470        let mut buf = [0u8; 8];
471        buf.as_mut_slice()
472            .write_u64_be(0x0102_0304_0506_0708)
473            .unwrap();
474        assert_eq!(buf, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]);
475    }
476
477    #[test]
478    fn write_i64_be_encodes_correctly() {
479        let mut buf = [0u8; 8];
480        buf.as_mut_slice().write_i64_be(-2).unwrap();
481        assert_eq!(buf, [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE]);
482    }
483
484    #[test]
485    fn write_u128_be_encodes_correctly() {
486        let mut buf = [0u8; 16];
487        buf.as_mut_slice().write_u128_be(1).unwrap();
488        assert_eq!(buf, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01]);
489    }
490
491    #[test]
492    fn write_i128_be_encodes_correctly() {
493        let mut buf = [0u8; 16];
494        buf.as_mut_slice().write_i128_be(-2).unwrap();
495        let expected = (-2_i128).to_be_bytes();
496        assert_eq!(buf, expected);
497    }
498
499    #[test]
500    fn write_f32_be_encodes_correctly() {
501        let val: f32 = 1.0;
502        let mut buf = [0u8; 4];
503        buf.as_mut_slice().write_f32_be(val).unwrap();
504        assert_eq!(buf, val.to_be_bytes());
505    }
506
507    #[test]
508    fn write_f64_be_encodes_correctly() {
509        let val: f64 = 1.0;
510        let mut buf = [0u8; 8];
511        buf.as_mut_slice().write_f64_be(val).unwrap();
512        assert_eq!(buf, val.to_be_bytes());
513    }
514
515    // --- Round-trip ---
516
517    #[test]
518    fn round_trip_f32() {
519        let val: f32 = core::f32::consts::PI;
520        let mut buf = [0u8; 4];
521        buf.as_mut_slice().write_f32_be(val).unwrap();
522        assert_eq!((&mut buf.as_slice()).read_f32_be().unwrap(), val);
523    }
524
525    #[test]
526    fn round_trip_f64() {
527        let val: f64 = core::f64::consts::PI;
528        let mut buf = [0u8; 8];
529        buf.as_mut_slice().write_f64_be(val).unwrap();
530        assert_eq!((&mut buf.as_slice()).read_f64_be().unwrap(), val);
531    }
532}