1use crate::core::{
2 ChannelData, FloFile, FloResult, Frame, FrameType, Header, ResidualEncoding, TocEntry,
3};
4use crate::MAGIC;
5use alloc::vec;
6use alloc::vec::Vec;
7
8pub struct Reader;
10
11impl Reader {
12 pub fn new() -> Self {
14 Reader
15 }
16
17 pub fn read(&self, data: &[u8]) -> FloResult<FloFile> {
19 let mut cursor = Cursor::new(data);
20
21 let magic = cursor.read_bytes(4)?;
23 if magic != MAGIC {
24 return Err("Invalid flo file: bad magic".into());
25 }
26
27 let header = self.read_header(&mut cursor)?;
29
30 let toc_size = usize::try_from(header.toc_size)
32 .map_err(|_| crate::core::FloError::from("TOC size does not fit in memory"))?;
33 let data_size = usize::try_from(header.data_size)
34 .map_err(|_| crate::core::FloError::from("DATA size does not fit in memory"))?;
35 let extra_size = usize::try_from(header.extra_size)
36 .map_err(|_| crate::core::FloError::from("EXTRA size does not fit in memory"))?;
37 let meta_size = usize::try_from(header.meta_size)
38 .map_err(|_| crate::core::FloError::from("META size does not fit in memory"))?;
39
40 let toc = self.read_toc(&mut cursor, toc_size)?;
41
42 let frames = self.read_data_chunk(&mut cursor, data_size, header.channels, &toc)?;
44
45 cursor.skip(extra_size)?;
47
48 let metadata = cursor.read_bytes(meta_size)?;
50
51 Ok(FloFile {
52 header,
53 toc,
54 frames,
55 extra: vec![],
56 metadata,
57 })
58 }
59
60 fn read_header(&self, cursor: &mut Cursor) -> FloResult<Header> {
61 Ok(Header {
62 version_major: cursor.read_u8()?,
63 version_minor: cursor.read_u8()?,
64 flags: cursor.read_u16_le()?,
65 sample_rate: cursor.read_u32_le()?,
66 channels: cursor.read_u8()?,
67 bit_depth: cursor.read_u8()?,
68 total_samples: cursor.read_u64_le()?,
69 compression_level: cursor.read_u8()?,
70 data_crc32: {
71 cursor.skip(3)?; cursor.read_u32_le()?
73 },
74 header_size: cursor.read_u64_le()?,
75 toc_size: cursor.read_u64_le()?,
76 data_size: cursor.read_u64_le()?,
77 extra_size: cursor.read_u64_le()?,
78 meta_size: cursor.read_u64_le()?,
79 })
80 }
81
82 fn read_toc(&self, cursor: &mut Cursor, toc_size: usize) -> FloResult<Vec<TocEntry>> {
83 if toc_size < 4 {
84 cursor.skip(toc_size)?;
85 return Ok(vec![]);
86 }
87
88 let toc_end = cursor.checked_end(toc_size)?;
89
90 let num_entries = cursor.read_u32_le()? as usize;
91
92 if num_entries > 100_000 {
93 return Err("Invalid TOC: too many entries".into());
94 }
95
96 let mut entries = Vec::with_capacity(num_entries);
97
98 for _ in 0..num_entries {
99 entries.push(TocEntry {
100 frame_index: cursor.read_u32_le()?,
101 byte_offset: cursor.read_u64_le()?,
102 frame_size: cursor.read_u32_le()?,
103 timestamp_ms: cursor.read_u32_le()?,
104 });
105 }
106
107 if cursor.pos > toc_end {
108 return Err("TOC entries exceed TOC size".into());
109 }
110 cursor.pos = toc_end;
111
112 Ok(entries)
113 }
114
115 fn read_data_chunk(
116 &self,
117 cursor: &mut Cursor,
118 data_size: usize,
119 channels: u8,
120 toc: &[TocEntry],
121 ) -> FloResult<Vec<Frame>> {
122 let data_start = cursor.pos;
123 let data_end = cursor.checked_end(data_size)?;
124 let mut frames = Vec::with_capacity(toc.len());
125
126 for toc_entry in toc.iter() {
127 let byte_offset = usize::try_from(toc_entry.byte_offset)
128 .map_err(|_| crate::core::FloError::from("Frame offset does not fit in memory"))?;
129 let frame_start = data_start.checked_add(byte_offset).ok_or_else(|| {
130 crate::core::FloError::from("Frame offset overflows memory address space")
131 })?;
132
133 if frame_start >= data_end {
134 return Err("Frame offset is outside DATA chunk".into());
135 }
136
137 cursor.pos = frame_start;
138 let frame_size = toc_entry.frame_size as usize;
139 let frame_end = frame_start.checked_add(frame_size).ok_or_else(|| {
140 crate::core::FloError::from("Frame size overflows memory address space")
141 })?;
142 if frame_end > data_end {
143 return Err("Frame exceeds DATA chunk".into());
144 }
145
146 let frame = self.read_frame(cursor, channels, frame_size)?;
147 frames.push(frame);
148 }
149
150 cursor.pos = data_end;
151 Ok(frames)
152 }
153
154 fn read_frame(&self, cursor: &mut Cursor, channels: u8, frame_size: usize) -> FloResult<Frame> {
155 let frame_start = cursor.pos;
156 let frame_end = frame_start.checked_add(frame_size).ok_or_else(|| {
157 crate::core::FloError::from("Frame size overflows memory address space")
158 })?;
159 if frame_end > cursor.data.len() {
160 return Err("Frame exceeds input data".into());
161 }
162
163 let frame_type_byte = cursor.read_u8()?;
165 let frame_samples = cursor.read_u32_le()?;
166 let flags = cursor.read_u8()?;
167
168 let frame_type = FrameType::from(frame_type_byte);
169 let mut frame = Frame::new(frame_type_byte, frame_samples);
170 frame.flags = flags;
171
172 let num_channels_to_read = if frame_type == FrameType::Transform {
174 1
175 } else {
176 channels as usize
177 };
178
179 for _ch_idx in 0..num_channels_to_read {
181 let ch_size = cursor.read_u32_le()? as usize;
183 let ch_end = cursor.pos.checked_add(ch_size).ok_or_else(|| {
184 crate::core::FloError::from("Channel size overflows memory address space")
185 })?;
186 if ch_end > frame_end {
187 return Err("Channel exceeds frame".into());
188 }
189
190 let ch_data =
191 self.read_channel_data(cursor, frame_type, frame_samples as usize, ch_end)?;
192 frame.channels.push(ch_data);
193
194 cursor.pos = ch_end;
196 }
197
198 cursor.pos = frame_end;
199 Ok(frame)
200 }
201
202 fn read_channel_data(
203 &self,
204 cursor: &mut Cursor,
205 frame_type: FrameType,
206 frame_samples: usize,
207 channel_end: usize,
208 ) -> FloResult<ChannelData> {
209 if frame_samples > 2_000_000 {
210 return Err("Invalid frame: too many samples".into());
211 }
212
213 match frame_type {
214 FrameType::Silence => Ok(ChannelData::new_silence()),
215
216 FrameType::Raw => {
217 let bytes_needed = frame_samples.saturating_mul(2);
218 let available = channel_end.saturating_sub(cursor.pos);
219 let bytes_to_read = bytes_needed.min(available);
220 let residuals = cursor.read_bytes(bytes_to_read)?;
221 Ok(ChannelData::new_raw(residuals))
222 }
223
224 FrameType::Transform => {
225 let remaining = channel_end.saturating_sub(cursor.pos);
227 let residuals = if remaining > 0 {
228 cursor.read_bytes(remaining)?
229 } else {
230 vec![]
231 };
232
233 Ok(ChannelData {
234 predictor_coeffs: vec![],
235 shift_bits: 0,
236 residual_encoding: ResidualEncoding::Raw,
237 rice_parameter: 0,
238 residuals,
239 })
240 }
241
242 _ if frame_type.is_alpc() => {
243 let order = cursor.read_u8()? as usize;
245
246 if order > 12 {
247 return Err("Invalid LPC order".into());
248 }
249
250 let mut predictor_coeffs = Vec::with_capacity(order);
252 for _ in 0..order {
253 if cursor
254 .pos
255 .checked_add(4)
256 .is_none_or(|end| end > channel_end)
257 {
258 break;
259 }
260 predictor_coeffs.push(cursor.read_i32_le()?);
261 }
262
263 let shift_bits = cursor.read_u8()?;
264
265 let residual_encoding_byte = cursor.read_u8()?;
266 let residual_encoding = ResidualEncoding::from(residual_encoding_byte);
267
268 let rice_parameter = if residual_encoding == ResidualEncoding::Rice {
270 cursor.read_u8()?
271 } else {
272 0
273 };
274
275 let remaining = channel_end.saturating_sub(cursor.pos);
277 let residuals = if remaining > 0 {
278 cursor.read_bytes(remaining)?
279 } else {
280 vec![]
281 };
282
283 Ok(ChannelData {
284 predictor_coeffs,
285 shift_bits,
286 residual_encoding,
287 rice_parameter,
288 residuals,
289 })
290 }
291
292 _ => Ok(ChannelData::new_silence()),
293 }
294 }
295}
296
297impl Default for Reader {
298 fn default() -> Self {
299 Self::new()
300 }
301}
302
303struct Cursor<'a> {
306 data: &'a [u8],
307 pos: usize,
308}
309
310impl<'a> Cursor<'a> {
311 fn new(data: &'a [u8]) -> Self {
312 Cursor { data, pos: 0 }
313 }
314
315 fn read_bytes(&mut self, count: usize) -> FloResult<Vec<u8>> {
316 let end = self.checked_end(count)?;
317 if end > self.data.len() {
318 return Err("Unexpected end of file".into());
319 }
320 let bytes = self.data[self.pos..end].to_vec();
321 self.pos = end;
322 Ok(bytes)
323 }
324
325 fn skip(&mut self, count: usize) -> FloResult<()> {
326 let end = self.checked_end(count)?;
327 if end > self.data.len() {
328 return Err("Unexpected end of file".into());
329 }
330 self.pos = end;
331 Ok(())
332 }
333
334 fn checked_end(&self, count: usize) -> FloResult<usize> {
335 self.pos
336 .checked_add(count)
337 .ok_or_else(|| "Input range overflows memory address space".into())
338 }
339
340 fn read_u8(&mut self) -> FloResult<u8> {
341 if self.pos >= self.data.len() {
342 return Err("Unexpected end of file".into());
343 }
344 let val = self.data[self.pos];
345 self.pos += 1;
346 Ok(val)
347 }
348
349 fn read_u16_le(&mut self) -> FloResult<u16> {
350 let bytes = self.read_bytes(2)?;
351 Ok(u16::from_le_bytes([bytes[0], bytes[1]]))
352 }
353
354 fn read_u32_le(&mut self) -> FloResult<u32> {
355 let bytes = self.read_bytes(4)?;
356 Ok(u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
357 }
358
359 fn read_i32_le(&mut self) -> FloResult<i32> {
360 let bytes = self.read_bytes(4)?;
361 Ok(i32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
362 }
363
364 fn read_u64_le(&mut self) -> FloResult<u64> {
365 let bytes = self.read_bytes(8)?;
366 Ok(u64::from_le_bytes([
367 bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
368 ]))
369 }
370}