dvb_si/descriptors/extension/
protection_message.rs1use super::*;
3
4impl<'a> ExtensionBodyDef<'a> for ProtectionMessage<'a> {
5 const TAG_EXTENSION: u8 = 0x18;
6 const NAME: &'static str = "PROTECTION_MESSAGE";
7}
8
9const MAX_COMPONENT_COUNT: usize = 0x0F;
11
12#[derive(Debug, Clone, PartialEq, Eq)]
15#[cfg_attr(feature = "serde", derive(serde::Serialize))]
16#[cfg_attr(feature = "yoke", derive(yoke::Yokeable))]
17pub struct ProtectionMessage<'a> {
18 pub reserved: u8,
20 #[cfg_attr(feature = "serde", serde(borrow))]
23 pub component_tags: &'a [u8],
24}
25
26impl<'a> Parse<'a> for ProtectionMessage<'a> {
27 type Error = crate::error::Error;
28 fn parse(sel: &'a [u8]) -> Result<Self> {
29 let first = *sel.first().ok_or(Error::BufferTooShort {
30 need: 1,
31 have: 0,
32 what: "protection_message body",
33 })?;
34 let reserved = first >> 4;
35 let component_count = usize::from(first & 0x0F);
36 let component_tags = sel
37 .get(1..1 + component_count)
38 .ok_or(Error::BufferTooShort {
39 need: 1 + component_count,
40 have: sel.len(),
41 what: "protection_message component_tags",
42 })?;
43 Ok(ProtectionMessage {
44 reserved,
45 component_tags,
46 })
47 }
48}
49
50impl Serialize for ProtectionMessage<'_> {
51 type Error = crate::error::Error;
52 fn serialized_len(&self) -> usize {
53 1 + self.component_tags.len()
54 }
55 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
56 if self.component_tags.len() > MAX_COMPONENT_COUNT {
57 return Err(Error::ValueOutOfRange {
58 field: "protection_message component_count",
59 reason: "more than 15 component_tags (4-bit field)",
60 });
61 }
62 let len = self.serialized_len();
63 if buf.len() < len {
64 return Err(Error::OutputBufferTooSmall {
65 need: len,
66 have: buf.len(),
67 });
68 }
69 buf[0] = ((self.reserved & 0x0F) << 4) | (self.component_tags.len() as u8 & 0x0F);
70 buf[1..len].copy_from_slice(self.component_tags);
71 Ok(len)
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78 use crate::descriptors::extension::test_support::*;
79 use crate::descriptors::extension::{ExtensionBody, ExtensionDescriptor};
80
81 #[test]
82 fn parse_protection_message_structured() {
83 let sel = [0xF3, 0x10, 0x20, 0x30];
85 let bytes = wrap(0x18, &sel);
86 let d = ExtensionDescriptor::parse(&bytes).unwrap();
87 match &d.body {
88 ExtensionBody::ProtectionMessage(b) => {
89 assert_eq!(b.reserved, 0x0F);
90 assert_eq!(b.component_tags, &[0x10, 0x20, 0x30]);
91 }
92 other => panic!("expected ProtectionMessage, got {other:?}"),
93 }
94 round_trip(&d);
95 }
96
97 #[test]
98 fn parse_protection_message_empty() {
99 let sel = [0xF0]; let bytes = wrap(0x18, &sel);
101 let d = ExtensionDescriptor::parse(&bytes).unwrap();
102 match &d.body {
103 ExtensionBody::ProtectionMessage(b) => assert!(b.component_tags.is_empty()),
104 other => panic!("expected ProtectionMessage, got {other:?}"),
105 }
106 round_trip(&d);
107 }
108
109 #[test]
110 fn serialize_rejects_oversized_component_list() {
111 let tags = [0u8; 16];
112 let pm = ProtectionMessage {
113 reserved: 0x0F,
114 component_tags: &tags,
115 };
116 let mut buf = [0u8; 32];
117 assert!(matches!(
118 pm.serialize_into(&mut buf),
119 Err(Error::ValueOutOfRange { .. })
120 ));
121 }
122}