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