1use std::io::Read;
2
3pub use error::ParseError;
4pub use error::Result;
5
6use std::fs::File;
7use std::path::Path;
8use std::io::BufReader;
9
10mod error;
11mod read_ext;
12
13mod opus_header_structs;
14pub use opus_header_structs::*;
15
16mod ogg_page;
17use ogg_page::*;
18
19#[cfg(test)]
20mod tests;
21
22#[derive(Debug)]
24pub struct OpusHeaders {
25 pub id: IdentificationHeader,
26 pub comments: CommentHeader,
27}
28
29pub fn parse_from_path<P: AsRef<Path>>(path: P) -> Result<OpusHeaders> {
33 parse_from_file(&File::open(path)?)
34}
35
36pub fn parse_from_file(file: &File) -> Result<OpusHeaders> {
40 parse_from_read(BufReader::new(file))
41}
42
43pub fn parse_from_read<T: Read>(mut reader: T) -> Result<OpusHeaders> {
47 let first_ogg_page = OggPage::parse(&mut reader)?;
48
49 let id = IdentificationHeader::parse(&first_ogg_page.payload[..])?;
50
51 let mut comment_pages = vec![];
52 comment_pages.push(OggPage::parse(&mut reader)?);
53
54 loop {
56 let next_page = OggPage::parse(&mut reader)?;
57 if next_page.header_type == 0x01 {
58 comment_pages.push(next_page);
59 } else {
60 break;
61 }
62 }
63
64 let comment_len = comment_pages.iter().map(|p| p.payload.len()).sum();
65 let mut comment_bytes = Vec::with_capacity(comment_len);
66
67 for mut page in comment_pages {
68 comment_bytes.append(&mut page.payload);
69 }
70
71 let co = CommentHeader::parse(&comment_bytes[..])?;
72
73 Ok(OpusHeaders { id, comments: co })
74}