1use std::fmt::Debug;
2use std::io;
3
4use scuffle_bytes_util::zero_copy::{Deserialize, DeserializeSeed, Serialize, U24Be, ZeroCopyReader};
5
6use crate::IsoSized;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum BoxSize {
13 Short(u32),
15 Long(u64),
17 ToEnd,
19}
20
21impl BoxSize {
22 pub fn size(&self) -> Option<usize> {
26 match self {
27 BoxSize::Short(size) => Some(*size as usize),
28 BoxSize::Long(size) => Some(*size as usize),
29 BoxSize::ToEnd => None,
30 }
31 }
32}
33
34impl From<usize> for BoxSize {
35 fn from(value: usize) -> Self {
36 if value > u32::MAX as usize || value == 0 || value == 1 {
39 BoxSize::Long(value as u64)
40 } else {
41 BoxSize::Short(value as u32)
42 }
43 }
44}
45
46#[derive(Clone, Copy, PartialEq, Eq)]
50pub enum BoxType {
51 FourCc([u8; 4]),
53 Uuid(uuid::Uuid),
55}
56
57impl Debug for BoxType {
58 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59 match self {
60 BoxType::FourCc(fourcc) => f.debug_tuple("FourCc").field(&String::from_utf8_lossy(fourcc)).finish(),
61 BoxType::Uuid(uuid) => f.debug_tuple("Uuid").field(uuid).finish(),
62 }
63 }
64}
65
66impl BoxType {
67 pub fn is_four_cc(&self, four_cc: &[u8; 4]) -> bool {
69 match self {
70 BoxType::FourCc(box_four_cc) => box_four_cc == four_cc,
71 BoxType::Uuid(_) => false,
72 }
73 }
74}
75
76impl From<BoxType> for uuid::Uuid {
77 fn from(box_type: BoxType) -> Self {
78 match box_type {
79 BoxType::FourCc(fourcc) => {
80 #[rustfmt::skip]
81 let bytes = [
82 fourcc[0], fourcc[1], fourcc[2], fourcc[3],
83 0x00, 0x11, 0x00, 0x10, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71,
84 ];
85 uuid::Uuid::from_bytes(bytes)
86 }
87 BoxType::Uuid(uuid) => uuid,
88 }
89 }
90}
91
92#[derive(Debug, PartialEq, Eq, Clone)]
98pub struct BoxHeader {
99 pub size: BoxSize,
102 pub box_type: BoxType,
104}
105
106impl IsoSized for BoxHeader {
107 fn size(&self) -> usize {
108 let mut size = 4 + 4; if let BoxSize::Long(_) = self.size {
111 size += 8; }
113
114 if let BoxType::Uuid(_) = self.box_type {
115 size += 16; }
117
118 size
119 }
120}
121
122impl BoxHeader {
123 pub fn payload_size(&self) -> Option<usize> {
127 let header_size = self.size();
128 Some(self.size.size()?.saturating_sub(header_size))
129 }
130}
131
132impl<'a> Deserialize<'a> for BoxHeader {
133 fn deserialize<R>(mut reader: R) -> io::Result<Self>
134 where
135 R: ZeroCopyReader<'a>,
136 {
137 let size = u32::deserialize(&mut reader)?;
138 let box_type = u32::deserialize(&mut reader)?.to_be_bytes();
139
140 let size = match size {
141 0 => BoxSize::ToEnd,
142 1 => {
143 let size = u64::deserialize(&mut reader)?;
144 BoxSize::Long(size)
145 }
146 _ => BoxSize::Short(size),
147 };
148
149 let box_type = if box_type == *b"uuid" {
150 let uuid = u128::deserialize(&mut reader)?;
151 let uuid = uuid::Uuid::from_u128(uuid);
152 BoxType::Uuid(uuid)
153 } else {
154 BoxType::FourCc(box_type)
155 };
156
157 Ok(Self { size, box_type })
158 }
159}
160
161impl<'a> DeserializeSeed<'a, BoxHeader> for BoxHeader {
162 fn deserialize_seed<R>(_reader: R, seed: BoxHeader) -> io::Result<Self>
163 where
164 R: ZeroCopyReader<'a>,
165 {
166 Ok(seed)
167 }
168}
169
170impl Serialize for BoxHeader {
171 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
172 where
173 W: std::io::Write,
174 {
175 let size = match self.size {
176 BoxSize::Short(size) => size,
177 BoxSize::Long(_) => 1,
178 BoxSize::ToEnd => 0,
179 };
180 size.serialize(&mut writer)?;
181
182 let box_type = match &self.box_type {
183 BoxType::FourCc(fourcc) => fourcc,
184 BoxType::Uuid(_) => b"uuid",
185 };
186 box_type.serialize(&mut writer)?;
187
188 if let BoxSize::Long(size) = self.size {
189 size.serialize(&mut writer)?;
190 }
191
192 if let BoxType::Uuid(uuid) = &self.box_type {
193 uuid.as_u128().to_be_bytes().serialize(&mut writer)?;
194 }
195
196 Ok(())
197 }
198}
199
200#[derive(Debug, PartialEq, Eq, Clone, Default)]
206pub struct FullBoxHeader {
207 pub version: u8,
209 pub flags: U24Be,
211}
212
213impl IsoSized for FullBoxHeader {
214 fn size(&self) -> usize {
215 1 + 3 }
218}
219
220impl<'a> Deserialize<'a> for FullBoxHeader {
221 fn deserialize<R>(mut reader: R) -> io::Result<Self>
222 where
223 R: ZeroCopyReader<'a>,
224 {
225 let version = u8::deserialize(&mut reader)?;
226 let flags = U24Be::deserialize(&mut reader)?;
227
228 Ok(Self { version, flags })
229 }
230}
231
232impl Serialize for FullBoxHeader {
233 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
234 where
235 W: std::io::Write,
236 {
237 self.version.serialize(&mut writer)?;
238 self.flags.serialize(&mut writer)?;
239
240 Ok(())
241 }
242}