1mod idat;
2mod iinf;
3mod iloc;
4mod ilst;
5mod iprp;
6mod iref;
7mod pitm;
8mod properties;
9
10pub use idat::*;
11pub use iinf::*;
12pub use iloc::*;
13pub use ilst::*;
14pub use iprp::*;
15pub use iref::*;
16pub use pitm::*;
17pub use properties::*;
18
19use crate::*;
20
21#[derive(Debug, Clone, PartialEq)]
27#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
28pub struct Meta {
29 pub hdlr: Hdlr,
30 pub pitm: Option<Pitm>,
31 pub dinf: Option<Dinf>,
32 pub iloc: Option<Iloc>,
33 pub iinf: Option<Iinf>,
34 pub iprp: Option<Iprp>,
35 pub iref: Option<Iref>,
36 pub idat: Option<Idat>,
37 pub ilst: Option<Ilst>,
38 pub unknown: Vec<crate::Any>,
39}
40
41impl Eq for Meta {}
42
43impl AtomExt for Meta {
44 type Ext = ();
45
46 const KIND_EXT: FourCC = FourCC::new(b"meta");
47
48 fn decode_body_ext<B: Buf>(buf: &mut B, _ext: ()) -> Result<Self> {
49 let hdlr = Hdlr::decode(buf)?;
50 let mut pitm = None;
51 let mut dinf = None;
52 let mut iloc = None;
53 let mut iinf = None;
54 let mut iprp = None;
55 let mut iref = None;
56 let mut idat = None;
57 let mut ilst = None;
58 let mut unknown_boxes = vec![];
59 while let Some(atom) = Any::decode_maybe(buf)? {
60 match atom {
61 Any::Pitm(atom) => pitm = Some(atom),
62 Any::Dinf(atom) => dinf = Some(atom),
63 Any::Iloc(atom) => iloc = Some(atom),
64 Any::Iinf(atom) => iinf = Some(atom),
65 Any::Iprp(atom) => iprp = Some(atom),
66 Any::Iref(atom) => iref = Some(atom),
67 Any::Idat(atom) => idat = Some(atom),
68 Any::Ilst(atom) => ilst = Some(atom),
69 _ => {
70 unknown_boxes.push(atom);
71 }
72 }
73 }
74
75 Ok(Self {
76 hdlr,
77 pitm,
78 dinf,
79 iloc,
80 iinf,
81 iprp,
82 iref,
83 idat,
84 ilst,
85 unknown: unknown_boxes,
86 })
87 }
88
89 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<()> {
90 self.hdlr.encode(buf)?;
91 if self.pitm.is_some() {
92 self.pitm.encode(buf)?;
93 }
94 if self.dinf.is_some() {
95 self.dinf.encode(buf)?;
96 }
97 if self.iloc.is_some() {
98 self.iloc.encode(buf)?;
99 }
100 if self.iinf.is_some() {
101 self.iinf.encode(buf)?;
102 }
103 if self.iprp.is_some() {
104 self.iprp.encode(buf)?;
105 }
106 if self.iref.is_some() {
107 self.iref.encode(buf)?;
108 }
109 if self.idat.is_some() {
110 self.idat.encode(buf)?;
111 }
112 if self.ilst.is_some() {
113 self.ilst.encode(buf)?;
114 }
115 for atom in &self.unknown {
116 atom.encode(buf)?;
117 }
118 Ok(())
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125
126 #[test]
127 fn test_meta_empty() {
128 let expected = Meta {
129 hdlr: Hdlr {
130 handler: b"fake".into(),
131 name: "".into(),
132 },
133 pitm: None,
134 dinf: None,
135 iloc: None,
136 iinf: None,
137 iprp: None,
138 iref: None,
139 idat: None,
140 ilst: None,
141 unknown: vec![],
142 };
143 let mut buf = Vec::new();
144 expected.encode(&mut buf).unwrap();
145
146 let mut buf = buf.as_ref();
147 let output = Meta::decode(&mut buf).unwrap();
148 assert_eq!(output, expected);
149 }
150
151 #[test]
152 fn test_meta_mdir() {
153 let expected = Meta {
154 hdlr: Hdlr {
155 handler: b"mdir".into(),
156 name: "".into(),
157 },
158 pitm: Some(Pitm { item_id: 3 }),
159 dinf: Some(Dinf {
160 dref: Dref {
161 urls: vec![Url {
162 location: "".into(),
163 }],
164 },
165 }),
166 iloc: Some(Iloc {
167 item_locations: vec![ItemLocation {
168 item_id: 3,
169 construction_method: 0,
170 data_reference_index: 0,
171 base_offset: 0,
172 extents: vec![ItemLocationExtent {
173 item_reference_index: 0,
174 offset: 200,
175 length: 100,
176 }],
177 }],
178 }),
179 iinf: Some(Iinf { item_infos: vec![] }),
180 iprp: Some(Iprp {
181 ipco: Ipco { properties: vec![] },
182 ipma: vec![Ipma {
183 item_properties: vec![
184 PropertyAssociations {
185 item_id: 1,
186 associations: vec![
187 PropertyAssociation {
188 essential: true,
189 property_index: 1,
190 },
191 PropertyAssociation {
192 essential: false,
193 property_index: 2,
194 },
195 PropertyAssociation {
196 essential: false,
197 property_index: 3,
198 },
199 PropertyAssociation {
200 essential: false,
201 property_index: 5,
202 },
203 PropertyAssociation {
204 essential: true,
205 property_index: 4,
206 },
207 ],
208 },
209 PropertyAssociations {
210 item_id: 2,
211 associations: vec![
212 PropertyAssociation {
213 essential: true,
214 property_index: 6,
215 },
216 PropertyAssociation {
217 essential: false,
218 property_index: 3,
219 },
220 PropertyAssociation {
221 essential: false,
222 property_index: 7,
223 },
224 PropertyAssociation {
225 essential: true,
226 property_index: 8,
227 },
228 PropertyAssociation {
229 essential: true,
230 property_index: 4,
231 },
232 ],
233 },
234 ],
235 }],
236 }),
237 iref: Some(Iref {
238 references: vec![Reference {
239 reference_type: b"cdsc".into(),
240 from_item_id: 2,
241 to_item_ids: vec![1, 3],
242 }],
243 }),
244 idat: Some(Idat {
245 data: vec![0x01, 0xFF, 0xFE, 0x03],
246 }),
247 ilst: Some(Ilst::default()),
248 unknown: vec![],
249 };
250 let mut buf = Vec::new();
251 expected.encode(&mut buf).unwrap();
252
253 let mut buf = buf.as_ref();
254 let output = Meta::decode(&mut buf).unwrap();
255 assert_eq!(output, expected);
256 }
257}