st377_1/
content_storage.rs1extern crate alloc;
5
6use alloc::vec::Vec;
7
8use broadcast_common::{Parse, Serialize};
9
10use crate::error::{Error, Result};
11use crate::local_set::{LocalSet, StructuralSetKind};
12use crate::sets::{
13 InterchangeObjectFields, LocalSetOwnedItem, collect_dark, finish_owned_set, get_optional_raw,
14 get_required_raw, owned_set_serialized_len, serialize_owned_set,
15};
16use crate::types::{UlBytes, parse_uid_batch, serialize_uid_batch};
17
18pub const TAG_PACKAGES: u16 = 0x1901;
20pub const TAG_ESSENCE_CONTAINER_DATA: u16 = 0x1902;
22
23const KNOWN_TAGS: [u16; 5] = [
24 crate::sets::TAG_INSTANCE_UID,
25 crate::sets::TAG_GENERATION_UID,
26 crate::sets::TAG_OBJECT_CLASS,
27 TAG_PACKAGES,
28 TAG_ESSENCE_CONTAINER_DATA,
29];
30
31#[derive(Debug, Clone, PartialEq, Eq)]
36pub struct ContentStorage {
37 pub interchange: InterchangeObjectFields,
39 pub packages: Vec<UlBytes>,
42 pub essence_container_data: Option<Vec<UlBytes>>,
45 pub dark: Vec<(u16, Vec<u8>)>,
47}
48
49impl<'a> Parse<'a> for ContentStorage {
50 type Error = Error;
51
52 fn parse(bytes: &'a [u8]) -> Result<Self> {
53 let set = LocalSet::parse(bytes)?;
54 if set.kind() != StructuralSetKind::ContentStorage {
55 return Err(Error::KeyPrefixMismatch {
56 what: "Content Storage (Table 17)",
57 });
58 }
59 let items = &set.items;
60 let interchange = InterchangeObjectFields::decode(items, "Content Storage")?;
61 let packages = parse_uid_batch(get_required_raw(
62 items,
63 TAG_PACKAGES,
64 "Packages",
65 "Content Storage",
66 )?)?;
67 let essence_container_data = get_optional_raw(items, TAG_ESSENCE_CONTAINER_DATA)
68 .map(parse_uid_batch)
69 .transpose()?;
70 let dark = collect_dark(items, &KNOWN_TAGS);
71
72 Ok(ContentStorage {
73 interchange,
74 packages,
75 essence_container_data,
76 dark,
77 })
78 }
79}
80
81impl ContentStorage {
82 fn owned_items(&self) -> Vec<LocalSetOwnedItem> {
83 let mut out = Vec::new();
84 self.interchange.encode_into(&mut out);
85 out.push(LocalSetOwnedItem::owned(
86 TAG_PACKAGES,
87 serialize_uid_batch(&self.packages),
88 ));
89 if let Some(ecd) = &self.essence_container_data {
90 out.push(LocalSetOwnedItem::owned(
91 TAG_ESSENCE_CONTAINER_DATA,
92 serialize_uid_batch(ecd),
93 ));
94 }
95 out
96 }
97}
98
99impl Serialize for ContentStorage {
100 type Error = Error;
101
102 fn serialized_len(&self) -> usize {
103 let (key, items) = finish_owned_set(
104 StructuralSetKind::ContentStorage,
105 self.owned_items(),
106 &self.dark,
107 );
108 owned_set_serialized_len(key, &items)
109 }
110
111 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
112 let (key, items) = finish_owned_set(
113 StructuralSetKind::ContentStorage,
114 self.owned_items(),
115 &self.dark,
116 );
117 serialize_owned_set(key, &items, buf)
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124
125 fn sample() -> ContentStorage {
126 ContentStorage {
127 interchange: InterchangeObjectFields {
128 instance_uid: [0x11; 16],
129 generation_uid: None,
130 object_class: None,
131 },
132 packages: alloc::vec![[0x22; 16], [0x33; 16]],
133 essence_container_data: Some(alloc::vec![[0x44; 16]]),
134 dark: Vec::new(),
135 }
136 }
137
138 #[test]
139 fn construct_serialize_parse_round_trip() {
140 let cs = sample();
141 let bytes = cs.to_bytes();
142 let parsed = ContentStorage::parse(&bytes).unwrap();
143 assert_eq!(parsed, cs);
144 assert_eq!(parsed.to_bytes(), bytes);
145 }
146
147 #[test]
148 fn optional_essence_container_data_omitted_round_trips() {
149 let mut cs = sample();
150 cs.essence_container_data = None;
151 let bytes = cs.to_bytes();
152 let parsed = ContentStorage::parse(&bytes).unwrap();
153 assert_eq!(parsed.essence_container_data, None);
154 assert_eq!(parsed.to_bytes(), bytes);
155 }
156
157 #[test]
158 fn mutation_changes_serialized_bytes() {
159 let mut cs = sample();
160 let before = cs.to_bytes();
161 cs.packages.push([0x55; 16]);
162 let after = cs.to_bytes();
163 assert_ne!(before, after);
164 }
165}