1use crate::*;
2
3ext! {
7 name: Iref,
8 versions: [0, 1],
9 flags: {}
10}
11
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct Reference {
14 pub reference_type: FourCC,
15 pub from_item_id: u32,
16 pub to_item_ids: Vec<u32>,
17}
18
19#[derive(Debug, Clone, PartialEq, Eq)]
20#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
21pub struct Iref {
22 pub references: Vec<Reference>,
23}
24
25impl AtomExt for Iref {
26 type Ext = IrefExt;
27
28 const KIND_EXT: FourCC = FourCC::new(b"iref");
29
30 fn decode_body_ext<B: Buf>(buf: &mut B, ext: IrefExt) -> Result<Self> {
31 let mut bytes_remaining = buf.remaining();
32 let mut references = vec![];
33 while bytes_remaining > 0 {
34 if ext.version == IrefVersion::V0 {
35 let box_len = u32::decode(buf)?;
36 bytes_remaining -= box_len as usize;
37 let reference_type = FourCC::decode(buf)?;
38 let from_item_id: u32 = u16::decode(buf)?.into();
39 let reference_count: u16 = u16::decode(buf)?;
40 let mut to_item_ids: Vec<u32> = vec![];
41 for _ in 0..reference_count {
42 let to_item_id: u32 = u16::decode(buf)?.into();
43 to_item_ids.push(to_item_id);
44 }
45 let reference = Reference {
46 reference_type,
47 from_item_id,
48 to_item_ids,
49 };
50 references.push(reference);
51 } else {
52 let box_len = u32::decode(buf)?;
53 bytes_remaining -= box_len as usize;
54 let reference_type = FourCC::decode(buf)?;
55 let from_item_id: u32 = u32::decode(buf)?;
56 let reference_count: u16 = u16::decode(buf)?;
57 let mut to_item_ids: Vec<u32> = vec![];
58 for _ in 0..reference_count {
59 let to_item_id: u32 = u32::decode(buf)?;
60 to_item_ids.push(to_item_id);
61 }
62 let reference = Reference {
63 reference_type,
64 from_item_id,
65 to_item_ids,
66 };
67 references.push(reference);
68 }
69 }
70 Ok(Iref { references })
71 }
72
73 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<IrefExt> {
74 let mut version = IrefVersion::V0;
75 'reference: for reference in &self.references {
76 if reference.from_item_id > (u16::MAX as u32) {
77 version = IrefVersion::V1;
78 break 'reference;
79 }
80 for id in &reference.to_item_ids {
81 if *id > (u16::MAX as u32) {
82 version = IrefVersion::V1;
83 break 'reference;
84 }
85 }
86 }
87 if version == IrefVersion::V0 {
88 for reference in &self.references {
89 let size = (4 + 4 + 2 + 2 + 2 * reference.to_item_ids.len()) as u32;
90 size.encode(buf)?;
91 reference.reference_type.encode(buf)?;
92 (reference.from_item_id as u16).encode(buf)?;
93 (reference.to_item_ids.len() as u16).encode(buf)?;
94 for id in &reference.to_item_ids {
95 (*id as u16).encode(buf)?;
96 }
97 }
98 } else {
99 for reference in &self.references {
100 let size = (4 + 4 + 4 + 2 + 4 * reference.to_item_ids.len()) as u32;
101 size.encode(buf)?;
102 reference.reference_type.encode(buf)?;
103 reference.from_item_id.encode(buf)?;
104 (reference.to_item_ids.len() as u16).encode(buf)?;
105 for id in &reference.to_item_ids {
106 id.encode(buf)?;
107 }
108 }
109 }
110 Ok(IrefExt { version })
111 }
112}