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    /// Convenience: allocate a `Vec` and serialise into it.
36    ///
37    /// # Panics
38    /// Panics if `serialize_into` returns an error on a buffer of exactly
39    /// `serialized_len()` bytes. For values obtained by parsing real wire data
40    /// this never happens; it can only occur for a **hand-constructed** value
41    /// that violates a wire constraint (e.g. a section whose body exceeds the
42    /// 12-bit `section_length`). When building values by hand and that's a
43    /// possibility, call [`serialize_into`](Self::serialize_into) and handle the
44    /// error instead.
45    fn to_bytes(&self) -> Vec<u8>
46    where
47        Self::Error: core::fmt::Debug,
48    {
49        let mut v = alloc::vec![0u8; self.serialized_len()];
50        self.serialize_into(&mut v)
51            .expect("serialize_into must succeed when buffer is exactly serialized_len()");
52        v
53    }
54
55    /// Allocate a `Vec` and serialize into it, returning the serializer's error instead of
56    /// panicking. Prefer this over [`to_bytes`](Self::to_bytes) for any value that was not
57    /// obtained by parsing (hand-built values can violate a wire constraint).
58    fn try_to_bytes(&self) -> Result<Vec<u8>, Self::Error> {
59        let mut v = alloc::vec![0u8; self.serialized_len()];
60        let written = self.serialize_into(&mut v)?;
61        // A serializer that writes fewer bytes than it promised must not
62        // leave trailing zeros in the result.
63        if written != v.len() {
64            v.truncate(written);
65        }
66        Ok(v)
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73    use core::fmt;
74
75    #[derive(Debug, PartialEq)]
76    struct TestError;
77
78    impl fmt::Display for TestError {
79        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80            f.write_str("test serializer error")
81        }
82    }
83
84    /// Minimal `Serialize` impl whose `serialize_into` fails when `fail` is set.
85    struct Flagged {
86        fail: bool,
87        written: usize,
88    }
89
90    impl Serialize for Flagged {
91        type Error = TestError;
92
93        fn serialized_len(&self) -> usize {
94            4
95        }
96
97        fn serialize_into(&self, buf: &mut [u8]) -> Result<usize, Self::Error> {
98            if self.fail {
99                return Err(TestError);
100            }
101            let n = self.written.min(buf.len());
102            buf[..n].copy_from_slice(&[1, 2, 3, 4][..n]);
103            Ok(n)
104        }
105    }
106
107    #[test]
108    fn try_to_bytes_returns_serializer_error() {
109        assert_eq!(
110            Flagged {
111                fail: true,
112                written: 0
113            }
114            .try_to_bytes(),
115            Err(TestError)
116        );
117    }
118
119    #[test]
120    #[should_panic]
121    fn to_bytes_panics_where_try_to_bytes_errors() {
122        let _ = Flagged {
123            fail: true,
124            written: 0,
125        }
126        .to_bytes();
127    }
128
129    #[test]
130    fn try_to_bytes_truncates_when_serializer_writes_less_than_promised() {
131        // serialized_len is 4 but only 3 bytes are written: no trailing zero.
132        let v = Flagged {
133            fail: false,
134            written: 3,
135        }
136        .try_to_bytes()
137        .unwrap();
138        assert_eq!(v, vec![1, 2, 3]);
139    }
140
141    #[test]
142    fn try_to_bytes_happy_path_matches_to_bytes() {
143        let ok = Flagged {
144            fail: false,
145            written: 4,
146        };
147        assert_eq!(ok.try_to_bytes().unwrap(), ok.to_bytes());
148    }
149}