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