1#![forbid(unsafe_code)]
4
5use bytes::Bytes;
6
7use crate::error::Error;
8use crate::types::{SampleFormat, WaveFormat};
9
10pub fn parse(data: &[u8]) -> Result<(WaveFormat, Bytes), Error> {
16 if data.len() < 12 || &data[0..4] != b"RIFF" || &data[8..12] != b"WAVE" {
17 return Err(Error::NotRiffWave);
18 }
19
20 let mut format = None;
21 let mut payload = None;
22 let mut pos = 12;
23 while pos + 8 <= data.len() {
24 let tag = &data[pos..pos + 4];
25 let size = u32::from_le_bytes([data[pos + 4], data[pos + 5], data[pos + 6], data[pos + 7]])
26 as usize;
27 let body_start = pos + 8;
28 let body_end = body_start.saturating_add(size).min(data.len());
29 let body = &data[body_start..body_end];
30
31 match tag {
32 b"fmt " => format = Some(parse_fmt_chunk(body)?),
33 b"data" => payload = Some(Bytes::copy_from_slice(body)),
34 _ => {}
35 }
36
37 pos = body_end + (size % 2); }
39
40 let format = format.ok_or(Error::MissingFmtChunk)?;
41 let payload = payload.unwrap_or_default();
42 Ok((format, payload))
43}
44
45fn parse_fmt_chunk(body: &[u8]) -> Result<WaveFormat, Error> {
46 if body.len() < 16 {
47 return Err(Error::TruncatedFmtChunk);
48 }
49 let tag = u16::from_le_bytes([body[0], body[1]]);
50 let sample_format = SampleFormat::from_tag(tag).ok_or(Error::UnsupportedFormatTag(tag))?;
51 let channels = u16::from_le_bytes([body[2], body[3]]);
52 let sample_rate = u32::from_le_bytes([body[4], body[5], body[6], body[7]]);
53 let bits_per_sample = u16::from_le_bytes([body[14], body[15]]);
54 Ok(WaveFormat {
55 sample_format,
56 channels,
57 sample_rate,
58 bits_per_sample,
59 })
60}
61
62#[cfg(test)]
63#[path = "demux_tests.rs"]
64mod tests;