1use crate::*;
2
3ext! {
7 name: Iinf,
8 versions: [0, 1],
9 flags: {}
10}
11
12ext! {
13 name: ItemInfoEntry,
14 versions: [0, 1, 2, 3],
15 flags: {item_not_in_presentation = 0,}
16}
17
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct ItemInfoEntry {
20 pub item_id: u32,
21 pub item_protection_index: u16,
22 pub item_type: Option<FourCC>,
23 pub item_name: String,
24 pub content_type: Option<String>,
25 pub content_encoding: Option<String>,
26 pub item_not_in_presentation: bool,
27}
28
29impl AtomExt for ItemInfoEntry {
30 const KIND_EXT: FourCC = FourCC::new(b"infe");
31
32 type Ext = ItemInfoEntryExt;
33
34 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<Self::Ext> {
35 let version: ItemInfoEntryVersion = if self.item_id > u16::MAX as u32 {
37 ItemInfoEntryVersion::V3
38 } else {
39 if self.item_type.is_some() {
41 ItemInfoEntryVersion::V2
42 } else {
43 ItemInfoEntryVersion::V0
44 }
45 };
46 if (version == ItemInfoEntryVersion::V0) || (version == ItemInfoEntryVersion::V1) {
47 (self.item_id as u16).encode(buf)?;
48 self.item_protection_index.encode(buf)?;
49 self.item_name.as_str().encode(buf)?;
50 self.content_type.clone().unwrap().as_str().encode(buf)?;
51 self.content_encoding
52 .clone()
53 .unwrap_or("".to_string())
54 .as_str()
55 .encode(buf)?;
56 if version == ItemInfoEntryVersion::V1 {
57 unimplemented!("infe extensions are not yet supported");
58 }
59 } else {
60 if version == ItemInfoEntryVersion::V2 {
61 (self.item_id as u16).encode(buf)?;
62 } else {
63 self.item_id.encode(buf)?;
64 }
65 self.item_protection_index.encode(buf)?;
66 Some(self.item_type).encode(buf)?;
67 self.item_name.as_str().encode(buf)?;
68 if self.item_type == Some(FourCC::new(b"mime")) {
69 self.content_type.clone().unwrap().as_str().encode(buf)?;
70 self.content_encoding
71 .clone()
72 .unwrap_or("".to_string())
73 .as_str()
74 .encode(buf)?;
75 }
76 }
77 Ok(ItemInfoEntryExt {
78 version,
79 item_not_in_presentation: self.item_not_in_presentation,
80 })
81 }
82
83 fn decode_body_ext<B: Buf>(buf: &mut B, ext: Self::Ext) -> Result<Self> {
84 let item_id: u32;
85 let item_protection_index;
86 let mut item_type = None;
87 let item_name;
88 let mut content_type = None;
89 let mut content_encoding = None;
90 if (ext.version == ItemInfoEntryVersion::V0) || (ext.version == ItemInfoEntryVersion::V1) {
91 item_id = u16::decode(buf)? as u32;
92 item_protection_index = u16::decode(buf)?;
93 item_name = String::decode(buf)?;
94 content_type = Some(String::decode(buf)?);
95 content_encoding = Some(String::decode(buf)?);
96 if ext.version == ItemInfoEntryVersion::V1 {
97 unimplemented!("infe extensions are not yet supported");
98 }
99 } else {
100 if ext.version == ItemInfoEntryVersion::V2 {
101 item_id = u16::decode(buf)? as u32;
102 } else {
103 item_id = u32::decode(buf)?;
104 }
105 item_protection_index = u16::decode(buf)?;
106 item_type = Some(FourCC::decode(buf)?);
107 item_name = String::decode(buf)?;
108 if item_type == Some(FourCC::new(b"mime")) {
109 content_type = Some(String::decode(buf)?);
110 content_encoding = Some(String::decode(buf)?);
111 }
112 }
113 Ok(ItemInfoEntry {
114 item_id,
115 item_protection_index,
116 item_type,
117 item_name,
118 content_type,
119 content_encoding,
120 item_not_in_presentation: ext.item_not_in_presentation,
121 })
122 }
123}
124
125#[derive(Debug, Clone, PartialEq, Eq)]
126#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
127pub struct Iinf {
128 pub item_infos: Vec<ItemInfoEntry>,
129}
130
131impl AtomExt for Iinf {
132 type Ext = IinfExt;
133
134 const KIND_EXT: FourCC = FourCC::new(b"iinf");
135
136 fn decode_body_ext<B: Buf>(buf: &mut B, ext: IinfExt) -> Result<Self> {
137 let mut item_infos = vec![];
138 let entry_count = if ext.version == IinfVersion::V0 {
139 u16::decode(buf)? as usize
140 } else {
141 u32::decode(buf)? as usize
142 };
143 for _ in 0..entry_count {
144 item_infos.push(ItemInfoEntry::decode(buf)?);
145 }
146 Ok(Iinf { item_infos })
147 }
148
149 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<IinfExt> {
150 let version;
151 if self.item_infos.len() > u16::MAX as usize {
152 version = IinfVersion::V1;
153 (self.item_infos.len() as u32).encode(buf)?
154 } else {
155 version = IinfVersion::V0;
156 (self.item_infos.len() as u16).encode(buf)?
157 }
158 for item_info in &self.item_infos {
159 item_info.encode(buf)?;
160 }
161
162 Ok(IinfExt { version })
163 }
164}