1use crate::*;
2
3use super::{Btrt, Pasp, Taic, Visual};
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7pub struct Uncv {
8 pub visual: Visual,
9 pub cmpd: Option<Cmpd>,
10 pub uncc: UncC,
11 pub btrt: Option<Btrt>,
12 pub ccst: Option<Ccst>,
13 pub pasp: Option<Pasp>,
14 pub taic: Option<Taic>,
15}
16
17impl Atom for Uncv {
18 const KIND: FourCC = FourCC::new(b"uncv");
19
20 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
21 let visual = Visual::decode(buf)?;
22
23 let mut ccst = None;
24 let mut cmpd = None;
25 let mut uncc = None;
26 let mut btrt = None;
27 let mut pasp = None;
28 let mut taic = None;
29 while let Some(atom) = Any::decode_maybe(buf)? {
30 match atom {
31 Any::Cmpd(atom) => cmpd = atom.into(),
32 Any::UncC(atom) => uncc = atom.into(),
33 Any::Btrt(atom) => btrt = atom.into(),
34 Any::Ccst(atom) => ccst = atom.into(),
35 Any::Pasp(atom) => pasp = atom.into(),
36 Any::Taic(atom) => taic = atom.into(),
37 unknown => Self::decode_unknown(&unknown)?,
38 }
39 }
40 skip_trailing_padding(buf);
41
42 Ok(Uncv {
43 visual,
44 cmpd,
45 uncc: uncc.ok_or(Error::MissingBox(UncC::KIND))?,
46 btrt,
47 ccst,
48 pasp,
49 taic,
50 })
51 }
52
53 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
54 self.visual.encode(buf)?;
55 self.cmpd.encode(buf)?;
56 self.uncc.encode(buf)?;
57 self.btrt.encode(buf)?;
58 self.ccst.encode(buf)?;
59 self.pasp.encode(buf)?;
60 self.taic.encode(buf)?;
61
62 Ok(())
63 }
64}
65
66#[derive(Debug, Clone, PartialEq, Eq)]
67#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
68pub struct Component {
69 pub component_type: u16,
70 pub component_type_uri: Option<String>,
71}
72
73#[derive(Debug, Clone, PartialEq, Eq, Default)]
74#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
75pub struct Cmpd {
76 pub components: Vec<Component>,
77}
78
79impl Atom for Cmpd {
80 const KIND: FourCC = FourCC::new(b"cmpd");
81
82 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
83 let component_count = u32::decode(buf)?;
84 let mut components: Vec<Component> =
85 Vec::with_capacity((component_count as usize).min(1024));
86 for _ in 0..component_count {
87 let component_type = u16::decode(buf)?;
88 if component_type >= 0x8000 {
89 let component_type_uri = String::decode(buf)?;
90 components.push(Component {
91 component_type,
92 component_type_uri: Some(component_type_uri),
93 });
94 } else {
95 components.push(Component {
96 component_type,
97 component_type_uri: None,
98 });
99 }
100 }
101 Ok(Cmpd { components })
102 }
103
104 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
105 let component_count: u32 = self.components.len() as u32;
106 component_count.encode(buf)?;
107 for component in &self.components {
108 component.component_type.encode(buf)?;
109 if component.component_type >= 0x8000 {
110 let component_type_uri = component
111 .component_type_uri
112 .as_ref()
113 .expect("Expected valid URI when component_type is >= 0x8000");
114 component_type_uri.as_str().encode(buf)?;
115 }
116 }
117 Ok(())
118 }
119}
120
121#[derive(Debug, Clone, PartialEq, Eq)]
122#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
123pub struct UncompressedComponent {
124 pub component_index: u16,
125 pub component_bit_depth_minus_one: u8,
126 pub component_format: u8,
127 pub component_align_size: u8,
128}
129
130ext! {
131 name: UncC,
132 versions: [0, 1],
133 flags: {}
134}
135
136#[derive(Debug, Clone, PartialEq, Eq)]
137#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
138pub enum UncC {
139 V1 {
140 profile: FourCC,
141 },
142 V0 {
143 profile: FourCC,
144 components: Vec<UncompressedComponent>,
145 sampling_type: u8, interleave_type: u8, block_size: u8,
148 components_little_endian: bool,
149 block_pad_lsb: bool,
150 block_little_endian: bool,
151 block_reversed: bool,
152 pad_unknown: bool,
153 pixel_size: u32,
154 row_align_size: u32,
155 tile_align_size: u32,
156 num_tile_cols_minus_one: u32,
157 num_tile_rows_minus_one: u32,
158 },
159}
160
161impl AtomExt for UncC {
162 const KIND_EXT: FourCC = FourCC::new(b"uncC");
163
164 type Ext = UncCExt;
165
166 fn decode_body_ext<B: Buf>(buf: &mut B, ext: UncCExt) -> Result<Self> {
167 match ext.version {
168 UncCVersion::V1 => Ok(UncC::V1 {
169 profile: FourCC::decode(buf)?,
170 }),
171 UncCVersion::V0 => {
172 let profile = FourCC::decode(buf)?;
173 let component_count = u32::decode(buf)?;
174 let mut components = Vec::with_capacity((component_count as usize).min(1024));
175 for _ in 0..component_count {
176 components.push(UncompressedComponent {
177 component_index: u16::decode(buf)?,
178 component_bit_depth_minus_one: u8::decode(buf)?,
179 component_format: u8::decode(buf)?,
180 component_align_size: u8::decode(buf)?,
181 });
182 }
183 let sampling_type = u8::decode(buf)?;
184 let interleave_type = u8::decode(buf)?;
185 let block_size = u8::decode(buf)?;
186 let flag_bits = u8::decode(buf)?;
187 let components_little_endian = flag_bits & 0x80 == 0x80;
188 let block_pad_lsb = flag_bits & 0x40 == 0x40;
189 let block_little_endian = flag_bits & 0x20 == 0x20;
190 let block_reversed = flag_bits & 0x10 == 0x10;
191 let pad_unknown = flag_bits & 0x08 == 0x08;
192 let pixel_size = u32::decode(buf)?;
193 let row_align_size = u32::decode(buf)?;
194 let tile_align_size = u32::decode(buf)?;
195 let num_tile_cols_minus_one = u32::decode(buf)?;
196 let num_tile_rows_minus_one = u32::decode(buf)?;
197 Ok(UncC::V0 {
198 profile,
199 components,
200 sampling_type,
201 interleave_type,
202 block_size,
203 components_little_endian,
204 block_pad_lsb,
205 block_little_endian,
206 block_reversed,
207 pad_unknown,
208 pixel_size,
209 row_align_size,
210 tile_align_size,
211 num_tile_cols_minus_one,
212 num_tile_rows_minus_one,
213 })
214 }
215 }
216 }
217
218 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<UncCExt> {
219 match self {
220 UncC::V1 { profile } => {
221 profile.encode(buf)?;
222 Ok(UncCExt {
223 version: UncCVersion::V1,
224 })
225 }
226 UncC::V0 {
227 profile,
228 components,
229 sampling_type,
230 interleave_type,
231 block_size,
232 components_little_endian,
233 block_pad_lsb,
234 block_little_endian,
235 block_reversed,
236 pad_unknown,
237 pixel_size,
238 row_align_size,
239 tile_align_size,
240 num_tile_cols_minus_one,
241 num_tile_rows_minus_one,
242 } => {
243 profile.encode(buf)?;
244 let component_count: u32 = components.len() as u32;
245 component_count.encode(buf)?;
246 for component in components {
247 component.component_index.encode(buf)?;
248 component.component_bit_depth_minus_one.encode(buf)?;
249 component.component_format.encode(buf)?;
250 component.component_align_size.encode(buf)?;
251 }
252 sampling_type.encode(buf)?;
253 interleave_type.encode(buf)?;
254 block_size.encode(buf)?;
255 let mut flags: u8 = 0x00;
256 if *components_little_endian {
257 flags |= 0x80u8;
258 }
259 if *block_pad_lsb {
260 flags |= 0x40u8;
261 }
262 if *block_little_endian {
263 flags |= 0x20u8;
264 }
265 if *block_reversed {
266 flags |= 0x10u8;
267 }
268 if *pad_unknown {
269 flags |= 0x08u8;
270 }
271 flags.encode(buf)?;
272 pixel_size.encode(buf)?;
273 row_align_size.encode(buf)?;
274 tile_align_size.encode(buf)?;
275 num_tile_cols_minus_one.encode(buf)?;
276 num_tile_rows_minus_one.encode(buf)?;
277 Ok(UncCExt {
278 version: UncCVersion::V0,
279 })
280 }
281 }
282 }
283}
284
285#[cfg(test)]
286mod tests {
287 use super::*;
288
289 const ENCODED_CMPD: &[u8] = &[
290 0x00, 0x00, 0x00, 0x12, 0x63, 0x6d, 0x70, 0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00,
291 0x05, 0x00, 0x06,
292 ];
293
294 const ENCODED_UNCC: &[u8] = &[
295 0x00, 0x00, 0x00, 0x3b, 0x75, 0x6e, 0x63, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
296 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00,
297 0x00, 0x02, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
299 ];
300
301 const ENCODED_CMPD_HUGE_COUNT: &[u8] = &[
304 0x00, 0x00, 0x00, 0x0c, 0x63, 0x6d, 0x70, 0x64, 0xff, 0xff, 0xff, 0xff,
305 ];
306
307 const ENCODED_UNCC_HUGE_COUNT: &[u8] = &[
308 0x00, 0x00, 0x00, 0x14, 0x75, 0x6e, 0x63, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
309 0x00, 0xff, 0xff, 0xff, 0xff,
310 ];
311
312 #[test]
313 fn test_cmpd_decode() {
314 let buf: &mut std::io::Cursor<&&[u8]> = &mut std::io::Cursor::new(&ENCODED_CMPD);
315
316 let cmpd = Cmpd::decode(buf).expect("failed to decode cmpd");
317
318 assert_eq!(
319 cmpd,
320 Cmpd {
321 components: vec![
322 Component {
323 component_type: 4,
324 component_type_uri: None
325 },
326 Component {
327 component_type: 5,
328 component_type_uri: None
329 },
330 Component {
331 component_type: 6,
332 component_type_uri: None
333 }
334 ]
335 },
336 );
337 }
338
339 #[test]
340 fn test_cmpd_huge_count() {
341 let buf = &mut std::io::Cursor::new(&ENCODED_CMPD_HUGE_COUNT);
342 assert!(matches!(Cmpd::decode(buf), Err(Error::OverDecode(_))));
343 }
344
345 #[test]
346 fn test_cmpd_encode() {
347 let cmpd = Cmpd {
348 components: vec![
349 Component {
350 component_type: 4,
351 component_type_uri: None,
352 },
353 Component {
354 component_type: 5,
355 component_type_uri: None,
356 },
357 Component {
358 component_type: 6,
359 component_type_uri: None,
360 },
361 ],
362 };
363
364 let mut buf = Vec::new();
365 cmpd.encode(&mut buf).unwrap();
366
367 assert_eq!(buf.as_slice(), ENCODED_CMPD);
368 }
369
370 #[test]
371 fn test_uncc_decode() {
372 let buf: &mut std::io::Cursor<&&[u8]> = &mut std::io::Cursor::new(&ENCODED_UNCC);
373
374 let uncc = UncC::decode(buf).expect("failed to decode uncC");
375
376 assert_eq!(
377 uncc,
378 UncC::V0 {
379 profile: FourCC::new(b"\0\0\0\0"),
380 components: vec![
381 UncompressedComponent {
382 component_index: 0,
383 component_bit_depth_minus_one: 7,
384 component_format: 0,
385 component_align_size: 0
386 },
387 UncompressedComponent {
388 component_index: 1,
389 component_bit_depth_minus_one: 7,
390 component_format: 0,
391 component_align_size: 0
392 },
393 UncompressedComponent {
394 component_index: 2,
395 component_bit_depth_minus_one: 7,
396 component_format: 0,
397 component_align_size: 0
398 },
399 ],
400 sampling_type: 0,
401 interleave_type: 1,
402 block_size: 0,
403 components_little_endian: false,
404 block_pad_lsb: false,
405 block_little_endian: false,
406 block_reversed: false,
407 pad_unknown: false,
408 pixel_size: 0,
409 row_align_size: 0,
410 tile_align_size: 0,
411 num_tile_cols_minus_one: 0,
412 num_tile_rows_minus_one: 0
413 }
414 );
415 }
416
417 #[test]
418 fn test_uncc_huge_count() {
419 let buf = &mut std::io::Cursor::new(&ENCODED_UNCC_HUGE_COUNT);
420 assert!(matches!(UncC::decode(buf), Err(Error::OverDecode(_))));
421 }
422
423 #[test]
424 fn test_uncc_encode() {
425 let uncc = UncC::V0 {
426 profile: FourCC::new(b"\0\0\0\0"),
427 components: vec![
428 UncompressedComponent {
429 component_index: 0,
430 component_bit_depth_minus_one: 7,
431 component_format: 0,
432 component_align_size: 0,
433 },
434 UncompressedComponent {
435 component_index: 1,
436 component_bit_depth_minus_one: 7,
437 component_format: 0,
438 component_align_size: 0,
439 },
440 UncompressedComponent {
441 component_index: 2,
442 component_bit_depth_minus_one: 7,
443 component_format: 0,
444 component_align_size: 0,
445 },
446 ],
447 sampling_type: 0,
448 interleave_type: 1,
449 block_size: 0,
450 components_little_endian: false,
451 block_pad_lsb: false,
452 block_little_endian: false,
453 block_reversed: false,
454 pad_unknown: false,
455 pixel_size: 0,
456 row_align_size: 0,
457 tile_align_size: 0,
458 num_tile_cols_minus_one: 0,
459 num_tile_rows_minus_one: 0,
460 };
461
462 let mut buf = Vec::new();
463 uncc.encode(&mut buf).unwrap();
464
465 assert_eq!(buf.as_slice(), ENCODED_UNCC);
466 }
467}