st377_1/
essence_container_data.rs1extern crate alloc;
7
8use alloc::vec::Vec;
9
10use broadcast_common::{Parse, Serialize};
11
12use crate::error::{Error, Result};
13use crate::local_set::{LocalSet, StructuralSetKind};
14use crate::sets::{
15 InterchangeObjectFields, LocalSetOwnedItem, collect_dark, finish_owned_set, get_optional_fixed,
16 get_required_fixed, owned_set_serialized_len, serialize_owned_set,
17};
18use crate::types::PackageId;
19
20pub const TAG_LINKED_PACKAGE_UID: u16 = 0x2701;
22pub const TAG_INDEX_SID: u16 = 0x3F06;
24pub const TAG_BODY_SID: u16 = 0x3F07;
26
27const KNOWN_TAGS: [u16; 6] = [
28 crate::sets::TAG_INSTANCE_UID,
29 crate::sets::TAG_GENERATION_UID,
30 crate::sets::TAG_OBJECT_CLASS,
31 TAG_LINKED_PACKAGE_UID,
32 TAG_INDEX_SID,
33 TAG_BODY_SID,
34];
35
36#[derive(Debug, Clone, PartialEq, Eq)]
46pub struct EssenceContainerData {
47 pub interchange: InterchangeObjectFields,
49 pub linked_package_uid: PackageId,
52 pub index_sid: Option<u32>,
55 pub body_sid: u32,
58 pub dark: Vec<(u16, Vec<u8>)>,
62}
63
64impl<'a> Parse<'a> for EssenceContainerData {
65 type Error = Error;
66
67 fn parse(bytes: &'a [u8]) -> Result<Self> {
68 let set = LocalSet::parse(bytes)?;
69 if set.kind() != StructuralSetKind::EssenceContainerData {
70 return Err(Error::KeyPrefixMismatch {
71 what: "Essence Container Data (Table 17)",
72 });
73 }
74 let items = &set.items;
75 let interchange = InterchangeObjectFields::decode(items, "Essence Container Data")?;
76 let linked_package_uid = PackageId(get_required_fixed::<32>(
77 items,
78 TAG_LINKED_PACKAGE_UID,
79 "Linked Package UID",
80 "Essence Container Data",
81 )?);
82 let index_sid =
83 get_optional_fixed::<4>(items, TAG_INDEX_SID, "IndexSID")?.map(u32::from_be_bytes);
84 let body_sid = u32::from_be_bytes(get_required_fixed::<4>(
85 items,
86 TAG_BODY_SID,
87 "BodySID",
88 "Essence Container Data",
89 )?);
90 let dark = collect_dark(items, &KNOWN_TAGS);
91
92 Ok(EssenceContainerData {
93 interchange,
94 linked_package_uid,
95 index_sid,
96 body_sid,
97 dark,
98 })
99 }
100}
101
102impl EssenceContainerData {
103 fn owned_items(&self) -> Vec<LocalSetOwnedItem> {
104 let mut out = Vec::new();
105 self.interchange.encode_into(&mut out);
106 out.push(LocalSetOwnedItem::fixed(
107 TAG_LINKED_PACKAGE_UID,
108 self.linked_package_uid.0,
109 ));
110 if let Some(idx) = self.index_sid {
111 out.push(LocalSetOwnedItem::fixed(TAG_INDEX_SID, idx.to_be_bytes()));
112 }
113 out.push(LocalSetOwnedItem::fixed(
114 TAG_BODY_SID,
115 self.body_sid.to_be_bytes(),
116 ));
117 out
118 }
119}
120
121impl Serialize for EssenceContainerData {
122 type Error = Error;
123
124 fn serialized_len(&self) -> usize {
125 let (key, items) = finish_owned_set(
126 StructuralSetKind::EssenceContainerData,
127 self.owned_items(),
128 &self.dark,
129 );
130 owned_set_serialized_len(key, &items)
131 }
132
133 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
134 let (key, items) = finish_owned_set(
135 StructuralSetKind::EssenceContainerData,
136 self.owned_items(),
137 &self.dark,
138 );
139 serialize_owned_set(key, &items, buf)
140 }
141}
142
143#[cfg(test)]
144mod tests {
145 use super::*;
146
147 fn sample() -> EssenceContainerData {
148 EssenceContainerData {
149 interchange: InterchangeObjectFields {
150 instance_uid: [0x11; 16],
151 generation_uid: None,
152 object_class: None,
153 },
154 linked_package_uid: PackageId([0x22; 32]),
155 index_sid: Some(1),
156 body_sid: 1,
157 dark: Vec::new(),
158 }
159 }
160
161 #[test]
162 fn construct_serialize_parse_round_trip() {
163 let ecd = sample();
164 let bytes = ecd.to_bytes();
165 let parsed = EssenceContainerData::parse(&bytes).unwrap();
166 assert_eq!(parsed, ecd);
167 assert_eq!(parsed.to_bytes(), bytes);
168 }
169
170 #[test]
171 fn null_package_id_round_trips() {
172 let mut ecd = sample();
173 ecd.linked_package_uid = PackageId::NULL;
174 ecd.index_sid = None;
175 ecd.body_sid = 0;
176 let bytes = ecd.to_bytes();
177 let parsed = EssenceContainerData::parse(&bytes).unwrap();
178 assert!(parsed.linked_package_uid.is_null());
179 assert_eq!(parsed.index_sid, None);
180 }
181
182 #[test]
183 fn dark_bool_properties_preserved() {
184 let mut ecd = sample();
185 ecd.dark = alloc::vec![(0x8010, alloc::vec![0x01])];
188 let bytes = ecd.to_bytes();
189 let parsed = EssenceContainerData::parse(&bytes).unwrap();
190 assert_eq!(parsed.dark, ecd.dark);
191 }
192}