opus_headers/
lib.rs

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/// Both headers contained in an opus file.
23#[derive(Debug)]
24pub struct OpusHeaders {
25    pub id: IdentificationHeader,
26    pub comments: CommentHeader,
27}
28
29/// Parses an opus file given by the path.
30/// Either returns the Opus Headers, or an error if anything goes wrong.
31/// This should not panic.
32pub fn parse_from_path<P: AsRef<Path>>(path: P) -> Result<OpusHeaders> {
33    parse_from_file(&File::open(path)?)
34}
35
36/// Parses an opus file given by the file parameter.
37/// Either returns the Opus Headers, or an error if anything goes wrong.
38/// This should not panic.
39pub fn parse_from_file(file: &File) -> Result<OpusHeaders> {
40    parse_from_read(BufReader::new(file))
41}
42
43/// Parses an opus file given by a reader.
44/// Either returns the Opus Headers, or an error if anything goes wrong.
45/// This should not panic.
46pub 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    // header 0x01 signals that the page is the continuation of a previous page
55    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}