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