scte104/operations/
insert_descriptor.rs1use alloc::vec::Vec;
7
8use crate::error::{Error, Result};
9use crate::traits::OperationDef;
10use broadcast_common::{Parse, Serialize};
11
12pub const OP_ID: u16 = 0x0108;
14
15#[derive(Debug, Clone, PartialEq, Eq, Default)]
17#[cfg_attr(feature = "serde", derive(serde::Serialize))]
18pub struct InsertDescriptor<'a> {
19 pub descriptor_count: u8,
21 #[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}