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}