Skip to main content

broadcast_common/
traits.rs

1//! Canonical `Parse` and `Serialize` traits for the DVB crate family.
2//!
3//! Each implementer picks its own error type via `type Error`, so
4//! domain-specific error variants stay visible to the caller.
5
6use alloc::vec::Vec;
7
8/// Parse a DVB structure from raw bytes. Borrowing allowed via `<'a>`; the
9/// concrete error type is chosen per implementer.
10pub trait Parse<'a>: Sized {
11    /// The error type this implementer returns. Typically the enclosing
12    /// crate's `Error` enum.
13    type Error;
14
15    /// Parse `bytes` as `Self`. Returns `Err(Self::Error)` on any protocol
16    /// violation or buffer underrun.
17    fn parse(bytes: &'a [u8]) -> Result<Self, Self::Error>;
18}
19
20/// Serialize a DVB structure back to bytes. Split from [`Parse`] so owned
21/// and borrowed variants of the same type can implement `Serialize`
22/// without carrying a lifetime.
23pub trait Serialize {
24    /// The error type this implementer returns (usually the same as the
25    /// corresponding [`Parse`] impl, but need not be).
26    type Error;
27
28    /// Number of bytes `serialize_into` will write.
29    fn serialized_len(&self) -> usize;
30
31    /// Write the serialised form into `buf`. Returns the number of bytes
32    /// written (always equal to `serialized_len()`).
33    fn serialize_into(&self, buf: &mut [u8]) -> Result<usize, Self::Error>;
34
35    /// Allocate a `Vec` and serialize into it, returning the serializer's error instead of
36    /// panicking. This is the only
37    /// allocate-and-serialize entry point: there is deliberately no panicking
38    /// `to_bytes` (hand-built values, or values assembled from damaged wire data,
39    /// can violate a wire constraint, so the error must reach the caller).
40    fn try_to_bytes(&self) -> Result<Vec<u8>, Self::Error> {
41        let mut v = alloc::vec![0u8; self.serialized_len()];
42        let written = self.serialize_into(&mut v)?;
43        // A serializer that writes fewer bytes than it promised must not
44        // leave trailing zeros in the result.
45        if written != v.len() {
46            v.truncate(written);
47        }
48        Ok(v)
49    }
50}
51
52#[cfg(test)]
53mod tests {
54    use super::*;
55    use alloc::vec;
56    use core::fmt;
57
58    #[derive(Debug, PartialEq)]
59    struct TestError;
60
61    impl fmt::Display for TestError {
62        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63            f.write_str("test serializer error")
64        }
65    }
66
67    /// Minimal `Serialize` impl whose `serialize_into` fails when `fail` is set.
68    struct Flagged {
69        fail: bool,
70        written: usize,
71    }
72
73    impl Serialize for Flagged {
74        type Error = TestError;
75
76        fn serialized_len(&self) -> usize {
77            4
78        }
79
80        fn serialize_into(&self, buf: &mut [u8]) -> Result<usize, Self::Error> {
81            if self.fail {
82                return Err(TestError);
83            }
84            let n = self.written.min(buf.len());
85            buf[..n].copy_from_slice(&[1, 2, 3, 4][..n]);
86            Ok(n)
87        }
88    }
89
90    #[test]
91    fn try_to_bytes_returns_serializer_error() {
92        assert_eq!(
93            Flagged {
94                fail: true,
95                written: 0
96            }
97            .try_to_bytes(),
98            Err(TestError)
99        );
100    }
101
102    #[test]
103    fn try_to_bytes_truncates_when_serializer_writes_less_than_promised() {
104        // serialized_len is 4 but only 3 bytes are written: no trailing zero.
105        let v = Flagged {
106            fail: false,
107            written: 3,
108        }
109        .try_to_bytes()
110        .unwrap();
111        assert_eq!(v, vec![1, 2, 3]);
112    }
113
114    #[test]
115    fn try_to_bytes_happy_path_fills_buffer() {
116        let ok = Flagged {
117            fail: false,
118            written: 4,
119        };
120        assert_eq!(ok.try_to_bytes().unwrap(), vec![1, 2, 3, 4]);
121    }
122}