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 core::fmt;
56
57 #[derive(Debug, PartialEq)]
58 struct TestError;
59
60 impl fmt::Display for TestError {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 f.write_str("test serializer error")
63 }
64 }
65
66 /// Minimal `Serialize` impl whose `serialize_into` fails when `fail` is set.
67 struct Flagged {
68 fail: bool,
69 written: usize,
70 }
71
72 impl Serialize for Flagged {
73 type Error = TestError;
74
75 fn serialized_len(&self) -> usize {
76 4
77 }
78
79 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize, Self::Error> {
80 if self.fail {
81 return Err(TestError);
82 }
83 let n = self.written.min(buf.len());
84 buf[..n].copy_from_slice(&[1, 2, 3, 4][..n]);
85 Ok(n)
86 }
87 }
88
89 #[test]
90 fn try_to_bytes_returns_serializer_error() {
91 assert_eq!(
92 Flagged {
93 fail: true,
94 written: 0
95 }
96 .try_to_bytes(),
97 Err(TestError)
98 );
99 }
100
101 #[test]
102 fn try_to_bytes_truncates_when_serializer_writes_less_than_promised() {
103 // serialized_len is 4 but only 3 bytes are written: no trailing zero.
104 let v = Flagged {
105 fail: false,
106 written: 3,
107 }
108 .try_to_bytes()
109 .unwrap();
110 assert_eq!(v, vec![1, 2, 3]);
111 }
112
113 #[test]
114 fn try_to_bytes_happy_path_fills_buffer() {
115 let ok = Flagged {
116 fail: false,
117 written: 4,
118 };
119 assert_eq!(ok.try_to_bytes().unwrap(), vec![1, 2, 3, 4]);
120 }
121}