Skip to main content

scte104/operations/
insert_descriptor.rs

1//! insert_descriptor_request_data() — ANSI/SCTE 104 2023 §9.8.5, Table 9-27 (opID 0x0108).
2//!
3//! Supplemental usage. Copies raw SCTE 35 descriptor images into the
4//! descriptor loop of the resulting splice_info_section.
5
6use alloc::vec::Vec;
7
8use crate::error::{Error, Result};
9use crate::traits::OperationDef;
10use broadcast_common::{Parse, Serialize};
11
12/// `opID` for insert_descriptor_request (§8.3, Table 8-4).
13pub const OP_ID: u16 = 0x0108;
14
15/// insert_descriptor_request_data() — §9.8.5, Table 9-27.
16#[derive(Debug, Clone, PartialEq, Eq, Default)]
17#[cfg_attr(feature = "serde", derive(serde::Serialize))]
18pub struct InsertDescriptor<'a> {
19    /// `descriptor_count` — 1 byte.
20    pub descriptor_count: u8,
21    /// Raw descriptor images (each follows MPEG-2 descriptor format:
22    /// tag(1) + length(1) + data(length)).
23    #[cfg_attr(feature = "serde", serde(borrow))]
24    pub descriptor_images: Vec<&'a [u8]>,
25}
26
27impl<'a> Parse<'a> for InsertDescriptor<'a> {
28    type Error = Error;
29    fn parse(bytes: &'a [u8]) -> Result<Self> {
30        if bytes.is_empty() {
31            return Err(Error::BufferTooShort {
32                need: 1,
33                have: 0,
34                what: "insert_descriptor descriptor_count",
35            });
36        }
37        let count = bytes[0] as usize;
38        let mut pos = 1;
39        let mut images = Vec::with_capacity(count);
40        for _ in 0..count {
41            if bytes.len() < pos + 2 {
42                return Err(Error::BufferTooShort {
43                    need: pos + 2,
44                    have: bytes.len(),
45                    what: "insert_descriptor tag+length",
46                });
47            }
48            let desc_len = bytes[pos + 1] as usize;
49            let total = 2 + desc_len;
50            if bytes.len() < pos + total {
51                return Err(Error::BufferTooShort {
52                    need: pos + total,
53                    have: bytes.len(),
54                    what: "insert_descriptor image",
55                });
56            }
57            images.push(&bytes[pos..pos + total]);
58            pos += total;
59        }
60        Ok(Self {
61            descriptor_count: count as u8,
62            descriptor_images: images,
63        })
64    }
65}
66
67impl Serialize for InsertDescriptor<'_> {
68    type Error = Error;
69    fn serialized_len(&self) -> usize {
70        1 + self
71            .descriptor_images
72            .iter()
73            .map(|img| img.len())
74            .sum::<usize>()
75    }
76    fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
77        let need = self.serialized_len();
78        if buf.len() < need {
79            return Err(Error::OutputBufferTooSmall {
80                need,
81                have: buf.len(),
82            });
83        }
84        buf[0] = self.descriptor_count;
85        let mut pos = 1;
86        for img in &self.descriptor_images {
87            buf[pos..pos + img.len()].copy_from_slice(img);
88            pos += img.len();
89        }
90        Ok(need)
91    }
92}
93
94impl<'a> OperationDef<'a> for InsertDescriptor<'a> {
95    const OP_ID: u16 = OP_ID;
96    const NAME: &'static str = "INSERT_DESCRIPTOR";
97}
98
99#[cfg(test)]
100mod tests {
101    use super::*;
102
103    #[test]
104    fn round_trip() {
105        let op = InsertDescriptor {
106            descriptor_count: 2,
107            descriptor_images: alloc::vec![
108                &[0xAB, 0x04, 0x01, 0x02, 0x03, 0x04][..],
109                &[0xCD, 0x02, 0xAA, 0xBB][..],
110            ],
111        };
112        let bytes = op.to_bytes();
113        let back = InsertDescriptor::parse(&bytes).unwrap();
114        assert_eq!(op, back);
115    }
116
117    #[test]
118    fn mutate_field_changes_output() {
119        let op = InsertDescriptor {
120            descriptor_count: 1,
121            descriptor_images: alloc::vec![&[0xAB, 0x04, 0x01, 0x02, 0x03, 0x04][..]],
122        };
123        let bytes = op.to_bytes();
124        let mut op2 = op.clone();
125        op2.descriptor_count = 2;
126        assert_ne!(op2.to_bytes(), bytes);
127    }
128}