1use crate::core::{
2 ChannelData, FloFile, FloResult, Frame, FrameType, Header, ResidualEncoding, TocEntry,
3};
4use crate::MAGIC;
5
6pub struct Reader;
8
9impl Reader {
10 pub fn new() -> Self {
12 Reader
13 }
14
15 pub fn read(&self, data: &[u8]) -> FloResult<FloFile> {
17 let mut cursor = Cursor::new(data);
18
19 let magic = cursor.read_bytes(4)?;
21 if magic != MAGIC {
22 return Err("Invalid flo file: bad magic".to_string());
23 }
24
25 let header = self.read_header(&mut cursor)?;
27
28 let toc = self.read_toc(&mut cursor, header.toc_size as usize)?;
30
31 let frames = self.read_data_chunk(
33 &mut cursor,
34 header.data_size as usize,
35 header.channels,
36 &toc,
37 )?;
38
39 cursor.skip(header.extra_size as usize)?;
41
42 let metadata = cursor.read_bytes(header.meta_size as usize)?;
44
45 Ok(FloFile {
46 header,
47 toc,
48 frames,
49 extra: vec![],
50 metadata,
51 })
52 }
53
54 fn read_header(&self, cursor: &mut Cursor) -> FloResult<Header> {
55 Ok(Header {
56 version_major: cursor.read_u8()?,
57 version_minor: cursor.read_u8()?,
58 flags: cursor.read_u16_le()?,
59 sample_rate: cursor.read_u32_le()?,
60 channels: cursor.read_u8()?,
61 bit_depth: cursor.read_u8()?,
62 total_frames: cursor.read_u64_le()?,
63 compression_level: cursor.read_u8()?,
64 data_crc32: {
65 cursor.skip(3)?; cursor.read_u32_le()?
67 },
68 header_size: cursor.read_u64_le()?,
69 toc_size: cursor.read_u64_le()?,
70 data_size: cursor.read_u64_le()?,
71 extra_size: cursor.read_u64_le()?,
72 meta_size: cursor.read_u64_le()?,
73 })
74 }
75
76 fn read_toc(&self, cursor: &mut Cursor, toc_size: usize) -> FloResult<Vec<TocEntry>> {
77 if toc_size < 4 {
78 return Ok(vec![]);
79 }
80
81 let num_entries = cursor.read_u32_le()? as usize;
82
83 if num_entries > 100_000 {
84 return Err("Invalid TOC: too many entries".to_string());
85 }
86
87 let mut entries = Vec::with_capacity(num_entries);
88
89 for _ in 0..num_entries {
90 entries.push(TocEntry {
91 frame_index: cursor.read_u32_le()?,
92 byte_offset: cursor.read_u64_le()?,
93 frame_size: cursor.read_u32_le()?,
94 timestamp_ms: cursor.read_u32_le()?,
95 });
96 }
97
98 Ok(entries)
99 }
100
101 fn read_data_chunk(
102 &self,
103 cursor: &mut Cursor,
104 data_size: usize,
105 channels: u8,
106 toc: &[TocEntry],
107 ) -> FloResult<Vec<Frame>> {
108 let data_start = cursor.pos;
109 let data_end = cursor.pos + data_size;
110 let mut frames = Vec::with_capacity(toc.len());
111
112 for toc_entry in toc.iter() {
113 let frame_start = data_start + toc_entry.byte_offset as usize;
114
115 if frame_start >= data_end {
116 break;
117 }
118
119 cursor.pos = frame_start;
120 let frame_size = toc_entry.frame_size as usize;
121
122 let frame = self.read_frame(cursor, channels, frame_size)?;
123 frames.push(frame);
124 }
125
126 cursor.pos = data_end;
127 Ok(frames)
128 }
129
130 fn read_frame(&self, cursor: &mut Cursor, channels: u8, frame_size: usize) -> FloResult<Frame> {
131 let frame_start = cursor.pos;
132 let frame_end = frame_start + frame_size;
133
134 let frame_type_byte = cursor.read_u8()?;
136 let frame_samples = cursor.read_u32_le()?;
137 let flags = cursor.read_u8()?;
138
139 let frame_type = FrameType::from(frame_type_byte);
140 let mut frame = Frame::new(frame_type_byte, frame_samples);
141 frame.flags = flags;
142
143 let num_channels_to_read = if frame_type == FrameType::Transform {
145 1
146 } else {
147 channels as usize
148 };
149
150 for _ch_idx in 0..num_channels_to_read {
152 let ch_size = cursor.read_u32_le()? as usize;
154 let ch_end = cursor.pos + ch_size;
155
156 let ch_data =
157 self.read_channel_data(cursor, frame_type, frame_samples as usize, ch_end)?;
158 frame.channels.push(ch_data);
159
160 cursor.pos = ch_end;
162 }
163
164 cursor.pos = frame_end;
165 Ok(frame)
166 }
167
168 fn read_channel_data(
169 &self,
170 cursor: &mut Cursor,
171 frame_type: FrameType,
172 frame_samples: usize,
173 channel_end: usize,
174 ) -> FloResult<ChannelData> {
175 if frame_samples > 2_000_000 {
176 return Err("Invalid frame: too many samples".to_string());
177 }
178
179 match frame_type {
180 FrameType::Silence => Ok(ChannelData::new_silence()),
181
182 FrameType::Raw => {
183 let bytes_needed = frame_samples.saturating_mul(2);
184 let available = channel_end.saturating_sub(cursor.pos);
185 let bytes_to_read = bytes_needed.min(available);
186 let residuals = cursor.read_bytes(bytes_to_read)?;
187 Ok(ChannelData::new_raw(residuals))
188 }
189
190 FrameType::Transform => {
191 let remaining = channel_end.saturating_sub(cursor.pos);
193 let residuals = if remaining > 0 {
194 cursor.read_bytes(remaining)?
195 } else {
196 vec![]
197 };
198
199 Ok(ChannelData {
200 predictor_coeffs: vec![],
201 shift_bits: 0,
202 residual_encoding: ResidualEncoding::Raw,
203 rice_parameter: 0,
204 residuals,
205 })
206 }
207
208 _ if frame_type.is_alpc() => {
209 let order = cursor.read_u8()? as usize;
211
212 if order > 12 {
213 return Err("Invalid LPC order".to_string());
214 }
215
216 let mut predictor_coeffs = Vec::with_capacity(order);
218 for _ in 0..order {
219 if cursor.pos + 4 > channel_end {
220 break;
221 }
222 predictor_coeffs.push(cursor.read_i32_le()?);
223 }
224
225 let shift_bits = cursor.read_u8()?;
226
227 let residual_encoding_byte = cursor.read_u8()?;
228 let residual_encoding = ResidualEncoding::from(residual_encoding_byte);
229
230 let rice_parameter = if residual_encoding == ResidualEncoding::Rice {
232 cursor.read_u8()?
233 } else {
234 0
235 };
236
237 let remaining = channel_end.saturating_sub(cursor.pos);
239 let residuals = if remaining > 0 {
240 cursor.read_bytes(remaining)?
241 } else {
242 vec![]
243 };
244
245 Ok(ChannelData {
246 predictor_coeffs,
247 shift_bits,
248 residual_encoding,
249 rice_parameter,
250 residuals,
251 })
252 }
253
254 _ => Ok(ChannelData::new_silence()),
255 }
256 }
257}
258
259impl Default for Reader {
260 fn default() -> Self {
261 Self::new()
262 }
263}
264
265struct Cursor<'a> {
268 data: &'a [u8],
269 pos: usize,
270}
271
272impl<'a> Cursor<'a> {
273 fn new(data: &'a [u8]) -> Self {
274 Cursor { data, pos: 0 }
275 }
276
277 fn read_bytes(&mut self, count: usize) -> FloResult<Vec<u8>> {
278 if self.pos + count > self.data.len() {
279 return Err("Unexpected end of file".to_string());
280 }
281 let bytes = self.data[self.pos..self.pos + count].to_vec();
282 self.pos += count;
283 Ok(bytes)
284 }
285
286 fn skip(&mut self, count: usize) -> FloResult<()> {
287 self.pos = (self.pos + count).min(self.data.len());
288 Ok(())
289 }
290
291 fn read_u8(&mut self) -> FloResult<u8> {
292 if self.pos >= self.data.len() {
293 return Err("Unexpected end of file".to_string());
294 }
295 let val = self.data[self.pos];
296 self.pos += 1;
297 Ok(val)
298 }
299
300 fn read_u16_le(&mut self) -> FloResult<u16> {
301 let bytes = self.read_bytes(2)?;
302 Ok(u16::from_le_bytes([bytes[0], bytes[1]]))
303 }
304
305 fn read_u32_le(&mut self) -> FloResult<u32> {
306 let bytes = self.read_bytes(4)?;
307 Ok(u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
308 }
309
310 fn read_i32_le(&mut self) -> FloResult<i32> {
311 let bytes = self.read_bytes(4)?;
312 Ok(i32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
313 }
314
315 fn read_u64_le(&mut self) -> FloResult<u64> {
316 let bytes = self.read_bytes(8)?;
317 Ok(u64::from_le_bytes([
318 bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
319 ]))
320 }
321}