use std::error;
use std::fmt;
use ::bitpacking::BitpackCursor;
use ::huffman_tree::{VorbisHuffmanTree, HuffmanError};
use std::io::{Cursor, ErrorKind, Read, Error};
use byteorder::{ReadBytesExt, LittleEndian};
use std::string::FromUtf8Error;
use header_cached::{CachedBlocksizeDerived, compute_bark_map_cos_omega};
#[derive(Debug)]
#[derive(PartialEq)]
pub enum HeaderReadError {
EndOfPacket,
NotVorbisHeader,
UnsupportedVorbisVersion,
HeaderBadFormat,
HeaderBadType(u8),
HeaderIsAudio,
Utf8DecodeError,
BufferNotAddressable,
}
impl From<()> for HeaderReadError {
fn from(_ :()) -> HeaderReadError {
HeaderReadError::EndOfPacket
}
}
impl From<HuffmanError> for HeaderReadError {
fn from(_ :HuffmanError) -> HeaderReadError {
HeaderReadError::HeaderBadFormat
}
}
impl From<Error> for HeaderReadError {
fn from(err :Error) -> HeaderReadError {
match err.kind() {
ErrorKind::UnexpectedEof => HeaderReadError::EndOfPacket,
_ => panic!("Non EOF Error occured when reading from Cursor<&[u8]>: {}", err),
}
}
}
impl From<FromUtf8Error> for HeaderReadError {
fn from(_ :FromUtf8Error) -> HeaderReadError {
HeaderReadError::Utf8DecodeError
}
}
impl error::Error for HeaderReadError {}
impl fmt::Display for HeaderReadError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
let description = match self {
HeaderReadError::EndOfPacket => "End of packet reached.",
HeaderReadError::NotVorbisHeader => "The packet is not a vorbis header",
HeaderReadError::UnsupportedVorbisVersion => "The vorbis version is not supported",
HeaderReadError::HeaderBadFormat => "Invalid header",
HeaderReadError::HeaderBadType(_) => "Invalid/unexpected header type",
HeaderReadError::HeaderIsAudio => "Packet seems to be audio",
HeaderReadError::Utf8DecodeError => "UTF-8 decoding error",
HeaderReadError::BufferNotAddressable => "Requested to create buffer of non-addressable size",
};
write!(fmt, "{}", description)
}
}
macro_rules! convert_to_usize {
( $val:expr, $val_type:ident ) => { {
let converted :usize = $val as usize;
if $val != converted as $val_type {
try!(Err(HeaderReadError::BufferNotAddressable));
}
converted
}}
}
macro_rules! read_header_begin_body {
( $rdr:expr ) => { {
let res = try!($rdr.read_u8());
if res & 1 == 0 {
try!(Err(HeaderReadError::HeaderIsAudio));
}
let is_vorbis =
try!($rdr.read_u8()) == 0x76 && try!($rdr.read_u8()) == 0x6f && try!($rdr.read_u8()) == 0x72 && try!($rdr.read_u8()) == 0x62 && try!($rdr.read_u8()) == 0x69 && try!($rdr.read_u8()) == 0x73; if !is_vorbis {
try!(Err(HeaderReadError::NotVorbisHeader));
}
return Ok(res);
}}
}
fn read_header_begin(rdr :&mut BitpackCursor) -> Result<u8, HeaderReadError> {
read_header_begin_body!(rdr)
}
fn read_header_begin_cursor(rdr :&mut Cursor<&[u8]>) -> Result<u8, HeaderReadError> {
read_header_begin_body!(rdr)
}
#[test]
fn test_read_hdr_begin() {
let test_arr = &[0x01, 0x76, 0x6f, 0x72,
0x62, 0x69, 0x72, 0x00, 0x00, 0x00, 0x00, 0x02,
0x44, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0xb5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0xb8, 0x01];
let mut rdr :BitpackCursor = BitpackCursor::new(test_arr);
assert_eq!(read_header_begin(&mut rdr), Err(HeaderReadError::NotVorbisHeader));
}
pub type HeaderSet = (IdentHeader, CommentHeader, SetupHeader);
pub struct IdentHeader {
pub audio_channels :u8,
pub audio_sample_rate :u32,
pub bitrate_maximum :i32,
pub bitrate_nominal :i32,
pub bitrate_minimum :i32,
pub blocksize_0 :u8,
pub blocksize_1 :u8,
pub(crate) cached_bs_derived :[CachedBlocksizeDerived; 2],
}
pub fn read_header_ident(packet :&[u8]) -> Result<IdentHeader, HeaderReadError> {
let mut rdr = BitpackCursor::new(packet);
let hd_id = try!(read_header_begin(&mut rdr));
if hd_id != 1 {
try!(Err(HeaderReadError::HeaderBadType(hd_id)));
}
let vorbis_version = try!(rdr.read_u32());
if vorbis_version != 0 {
try!(Err(HeaderReadError::UnsupportedVorbisVersion));
}
let audio_channels = try!(rdr.read_u8());
let audio_sample_rate = try!(rdr.read_u32());
let bitrate_maximum = try!(rdr.read_i32());
let bitrate_nominal = try!(rdr.read_i32());
let bitrate_minimum = try!(rdr.read_i32());
let blocksize_0 = try!(rdr.read_u4());
let blocksize_1 = try!(rdr.read_u4());
let framing = try!(rdr.read_u8());
if blocksize_0 < 6 || blocksize_0 > 13 ||
blocksize_1 < 6 || blocksize_1 > 13 ||
(framing != 1) || blocksize_0 > blocksize_1 ||
audio_channels == 0 || audio_sample_rate == 0 {
try!(Err(HeaderReadError::HeaderBadFormat));
}
let hdr :IdentHeader = IdentHeader {
audio_channels,
audio_sample_rate,
bitrate_maximum,
bitrate_nominal,
bitrate_minimum,
blocksize_0,
blocksize_1,
cached_bs_derived : [
CachedBlocksizeDerived::from_blocksize(blocksize_0),
CachedBlocksizeDerived::from_blocksize(blocksize_1),
],
};
return Ok(hdr);
}
#[test]
fn test_read_header_ident() {
let test_arr = &[0x01, 0x76, 0x6f, 0x72,
0x62, 0x69, 0x73, 0x00, 0x00, 0x00, 0x00, 0x02,
0x44, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0xb5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0xb8, 0x01];
let hdr = read_header_ident(test_arr).unwrap();
assert_eq!(hdr.audio_channels, 2);
assert_eq!(hdr.audio_sample_rate, 0x0000ac44);
assert_eq!(hdr.bitrate_maximum, 0);
assert_eq!(hdr.bitrate_nominal, 0x0001b580);
assert_eq!(hdr.bitrate_minimum, 0);
assert_eq!(hdr.blocksize_0, 8);
assert_eq!(hdr.blocksize_1, 11);
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct CommentHeader {
pub vendor :String,
pub comment_list :Vec<(String, String)>,
}
pub fn read_header_comment(packet :&[u8]) -> Result<CommentHeader, HeaderReadError> {
let mut rdr = Cursor::new(packet);
let hd_id = try!(read_header_begin_cursor(&mut rdr));
if hd_id != 3 {
try!(Err(HeaderReadError::HeaderBadType(hd_id)));
}
let vendor_length = try!(rdr.read_u32::<LittleEndian>()) as usize;
let mut vendor_buf = vec![0; vendor_length]; try!(rdr.read_exact(&mut vendor_buf));
let vendor = try!(String::from_utf8(vendor_buf));
let comment_count = try!(rdr.read_u32::<LittleEndian>()) as usize;
let mut comment_list = Vec::with_capacity(comment_count);
for _ in 0 .. comment_count {
let comment_length = try!(rdr.read_u32::<LittleEndian>()) as usize;
let mut comment_buf = vec![0; comment_length]; try!(rdr.read_exact(&mut comment_buf));
let comment = match String::from_utf8(comment_buf) {
Ok(comment) => comment,
Err(_) => continue,
};
let eq_idx = match comment.find("=") {
Some(k) => k,
None => continue };
let (key_eq, val) = comment.split_at(eq_idx + 1);
let (key, _) = key_eq.split_at(eq_idx);
comment_list.push((String::from(key), String::from(val)));
}
let framing = try!(rdr.read_u8());
if framing != 1 {
try!(Err(HeaderReadError::HeaderBadFormat));
}
let hdr :CommentHeader = CommentHeader {
vendor,
comment_list,
};
return Ok(hdr);
}
pub(crate) struct Codebook {
pub codebook_dimensions :u16,
pub codebook_entries :u32,
pub codebook_vq_lookup_vec :Option<Vec<f32>>,
pub codebook_huffman_tree :VorbisHuffmanTree,
}
pub(crate) struct Residue {
pub residue_type :u8,
pub residue_begin :u32,
pub residue_end :u32,
pub residue_partition_size :u32,
pub residue_classifications :u8,
pub residue_classbook :u8,
pub residue_books :Vec<ResidueBook>,
}
pub(crate) struct Mapping {
pub mapping_submaps :u8,
pub mapping_magnitudes :Vec<u8>,
pub mapping_angles :Vec<u8>,
pub mapping_mux :Vec<u8>,
pub mapping_submap_floors :Vec<u8>,
pub mapping_submap_residues :Vec<u8>,
}
pub(crate) struct ModeInfo {
pub mode_blockflag :bool,
pub mode_mapping :u8,
}
pub(crate) enum Floor {
TypeZero(FloorTypeZero),
TypeOne(FloorTypeOne),
}
pub(crate) struct FloorTypeZero {
pub floor0_order :u8,
pub floor0_rate :u16,
pub floor0_bark_map_size :u16,
pub floor0_amplitude_bits :u8,
pub floor0_amplitude_offset :u8,
pub floor0_number_of_books :u8,
pub floor0_book_list :Vec<u8>,
pub cached_bark_cos_omega :[Vec<f32>; 2],
}
pub(crate) struct FloorTypeOne {
pub floor1_multiplier :u8,
pub floor1_partition_class :Vec<u8>,
pub floor1_class_dimensions :Vec<u8>,
pub floor1_class_subclasses :Vec<u8>,
pub floor1_subclass_books :Vec<Vec<i16>>,
pub floor1_class_masterbooks :Vec<u8>,
pub floor1_x_list :Vec<u32>,
pub floor1_x_list_sorted :Vec<(usize, u32)>,
}
pub(crate) struct ResidueBook {
vals_used :u8,
val_i :[u8; 8],
}
impl ResidueBook {
pub fn get_val(&self, i :u8) -> Option<u8> {
if i >= 8 {
panic!("Tried to get ResidueBook value out of bounds (index = {})",
i);
}
return if self.vals_used & (1 << i) > 0 {
Some(self.val_i[i as usize])
} else {
None
};
}
fn read_book(rdr :&mut BitpackCursor,
vals_used :u8, codebooks :&[Codebook])
-> Result<Self, HeaderReadError> {
let mut val_i :[u8; 8] = [0; 8];
for i in 0 .. 7 {
if vals_used & (1 << i) == 0 {
continue;
}
let val_entry = try!(rdr.read_u8());
if match codebooks.get(val_entry as usize) {
Some(v) => v.codebook_vq_lookup_vec.is_none(),
None => true,
} {
try!(Err(HeaderReadError::HeaderBadFormat))
}
val_i[i] = val_entry;
}
return Ok(ResidueBook { vals_used, val_i });
}
}
pub struct SetupHeader {
pub(crate) codebooks :Vec<Codebook>,
pub(crate) floors :Vec<Floor>,
pub(crate) residues :Vec<Residue>,
pub(crate) mappings :Vec<Mapping>,
pub(crate) modes :Vec<ModeInfo>,
}
struct CodebookVqLookup {
codebook_lookup_type :u8,
codebook_minimum_value :f32,
codebook_delta_value :f32,
codebook_sequence_p :bool,
codebook_multiplicands :Vec<u32>,
}
fn lookup_vec_val_decode(lup :&CodebookVqLookup, codebook_entries :u32, codebook_dimensions :u16) -> Vec<f32> {
let mut value_vectors = Vec::with_capacity(
codebook_entries as usize * codebook_dimensions as usize);
if lup.codebook_lookup_type == 1 {
let codebook_lookup_values = lup.codebook_multiplicands.len();
for lookup_offset in 0 .. codebook_entries {
let mut last = 0.;
let mut index_divisor = 1;
for _ in 0 .. codebook_dimensions {
let multiplicand_offset = (lookup_offset / index_divisor as u32) as usize %
codebook_lookup_values;
let vec_elem = lup.codebook_multiplicands[multiplicand_offset] as f32 *
lup.codebook_delta_value + lup.codebook_minimum_value + last;
if lup.codebook_sequence_p {
last = vec_elem;
}
value_vectors.push(vec_elem);
index_divisor *= codebook_lookup_values;
}
}
} else {
for lookup_offset in 0 .. codebook_entries {
let mut last = 0.;
let mut multiplicand_offset :usize = lookup_offset as usize * codebook_dimensions as usize;
for _ in 0 .. codebook_dimensions {
let vec_elem = lup.codebook_multiplicands[multiplicand_offset] as f32 *
lup.codebook_delta_value + lup.codebook_minimum_value + last;
if lup.codebook_sequence_p {
last = vec_elem;
}
value_vectors.push(vec_elem);
multiplicand_offset += 1;
}
}
}
return value_vectors;
}
pub(crate) enum HuffmanVqReadErr {
EndOfPacket,
NoVqLookupForCodebook,
}
impl <'a> BitpackCursor <'a> {
pub(crate) fn read_huffman_vq<'b>(&mut self, b :&'b Codebook) -> Result<&'b[f32], HuffmanVqReadErr> {
let idx = match self.read_huffman(&b.codebook_huffman_tree) {
Ok(v) => v as usize,
Err(_) => return Err(HuffmanVqReadErr::EndOfPacket),
};
let codebook_vq_lookup_vec :&[f32] = match b.codebook_vq_lookup_vec.as_ref() {
Some(ref v) => v,
None => return Err(HuffmanVqReadErr::NoVqLookupForCodebook),
};
let dim = b.codebook_dimensions as usize;
return Ok(&codebook_vq_lookup_vec[idx * dim .. (idx + 1) * dim]);
}
}
static MAX_BASES_WITHOUT_OVERFLOW : &[u32] = &[
0xffffffff, 0xffffffff, 0x0000ffff, 0x00000659,
0x000000ff, 0x00000054, 0x00000028, 0x00000017,
0x0000000f, 0x0000000b, 0x00000009, 0x00000007,
0x00000006, 0x00000005, 0x00000004, 0x00000004,
0x00000003, 0x00000003, 0x00000003, 0x00000003,
0x00000003, 0x00000002, 0x00000002, 0x00000002,
0x00000002, 0x00000002, 0x00000002, 0x00000002,
0x00000002, 0x00000002, 0x00000002, 0x00000002];
static MAX_BASE_MAX_BITS_WITHOUT_OVERFLOW : &[u8] = &[
0x1f, 0x1f, 0x0f, 0x0a,
0x07, 0x06, 0x05, 0x04,
0x03, 0x03, 0x03, 0x02,
0x02, 0x02, 0x02, 0x02,
0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01];
fn exp_fast(base :u32, exponent: u8) -> u32 {
let mut res :u32 = 1;
let mut selfmul = base;
for i in 0 .. 8 {
if (1 << i) & exponent > 0 {
res *= selfmul;
}
if let Some(newselfmul) = u32::checked_mul(selfmul, selfmul) {
selfmul = newselfmul;
} else {
if i < 7 && (exponent >> (i + 1)) > 0 {
panic!("Overflow when squaring for exp_fast, \
precondition violated!");
}
return res;
}
}
return res;
}
fn lookup1_values(codebook_entries :u32, codebook_dimensions :u16) -> u32 {
if codebook_dimensions >= 32 {
return if codebook_entries == 0 { 0 } else { 1 };
}
let max_base_bits = MAX_BASE_MAX_BITS_WITHOUT_OVERFLOW[
codebook_dimensions as usize];
let max_base = MAX_BASES_WITHOUT_OVERFLOW[codebook_dimensions as usize];
let mut base_bits :u32 = 0;
for i in 0 .. max_base_bits + 1 {
let cur_disputed_bit :u32 = 1 << (max_base_bits - i);
base_bits |= cur_disputed_bit;
if max_base < base_bits ||
exp_fast(base_bits, codebook_dimensions as u8) > codebook_entries {
base_bits &= !cur_disputed_bit;
}
}
return base_bits;
}
#[test]
fn test_lookup1_values() {
assert_eq!(lookup1_values(1025, 10), 2);
assert_eq!(lookup1_values(1024, 10), 2);
assert_eq!(lookup1_values(1023, 10), 1);
assert_eq!(lookup1_values(3126, 5), 5);
assert_eq!(lookup1_values(3125, 5), 5);
assert_eq!(lookup1_values(3124, 5), 4);
assert_eq!(lookup1_values(1, 1), 1);
assert_eq!(lookup1_values(0, 15), 0);
assert_eq!(lookup1_values(0, 0), 0);
assert_eq!(lookup1_values(1, 0), std::u32::MAX);
assert_eq!(lookup1_values(400, 0), std::u32::MAX);
}
fn read_codebook(rdr :&mut BitpackCursor) -> Result<Codebook, HeaderReadError> {
let sync_pattern = try!(rdr.read_u24());
if sync_pattern != 0x564342 {
try!(Err(HeaderReadError::HeaderBadFormat));
}
let codebook_dimensions = try!(rdr.read_u16());
let codebook_entries = try!(rdr.read_u24());
let ordered = try!(rdr.read_bit_flag());
let mut codebook_codeword_lengths = Vec::with_capacity(
convert_to_usize!(codebook_entries, u32));
if !ordered {
let sparse = try!(rdr.read_bit_flag());
for _ in 0 .. codebook_entries {
let length = if sparse {
let flag = try!(rdr.read_bit_flag());
if flag {
try!(rdr.read_u5()) + 1
} else {
0
}
} else {
try!(rdr.read_u5()) + 1
};
codebook_codeword_lengths.push(length);
}
} else {
let mut current_entry :u32 = 0;
let mut current_length = try!(rdr.read_u5()) + 1;
while current_entry < codebook_entries {
let number = try!(rdr.read_dyn_u32(
::ilog((codebook_entries - current_entry) as u64)));
for _ in current_entry .. current_entry + number {
codebook_codeword_lengths.push(current_length);
}
current_entry += number;
current_length += 1;
if current_entry as u32 > codebook_entries {
try!(Err(HeaderReadError::HeaderBadFormat));
}
}
}
let codebook_lookup_type = try!(rdr.read_u4());
if codebook_lookup_type > 2 {
try!(Err(HeaderReadError::HeaderBadFormat));
}
let codebook_lookup :Option<CodebookVqLookup> =
if codebook_lookup_type == 0 {
None
} else {
let codebook_minimum_value = try!(rdr.read_f32());
let codebook_delta_value = try!(rdr.read_f32());
let codebook_value_bits = try!(rdr.read_u4()) + 1;
let codebook_sequence_p = try!(rdr.read_bit_flag());
let codebook_lookup_values :u64 = if codebook_lookup_type == 1 {
lookup1_values(codebook_entries, codebook_dimensions) as u64
} else {
codebook_entries as u64 * codebook_dimensions as u64
};
let mut codebook_multiplicands = Vec::with_capacity(
convert_to_usize!(codebook_lookup_values, u64));
for _ in 0 .. codebook_lookup_values {
codebook_multiplicands.push(try!(rdr.read_dyn_u32(codebook_value_bits)));
}
Some(CodebookVqLookup {
codebook_lookup_type,
codebook_minimum_value,
codebook_delta_value,
codebook_sequence_p,
codebook_multiplicands,
})
};
let codebook_vq_lookup_vec = codebook_lookup.as_ref().map(|lup| {
lookup_vec_val_decode(lup,
codebook_entries, codebook_dimensions)
});
return Ok(Codebook {
codebook_dimensions,
codebook_entries,
codebook_vq_lookup_vec,
codebook_huffman_tree : try!(VorbisHuffmanTree::load_from_array(&codebook_codeword_lengths)),
});
}
fn read_floor(rdr :&mut BitpackCursor, codebook_cnt :u16, blocksizes :(u8, u8)) ->
Result<Floor, HeaderReadError> {
let floor_type = try!(rdr.read_u16());
match floor_type {
0 => {
let floor0_order = try!(rdr.read_u8());
let floor0_rate = try!(rdr.read_u16());
let floor0_bark_map_size = try!(rdr.read_u16());
let floor0_amplitude_bits = try!(rdr.read_u6());
if floor0_amplitude_bits > 64 {
try!(Err(HeaderReadError::HeaderBadFormat));
}
let floor0_amplitude_offset = try!(rdr.read_u8());
let floor0_number_of_books = try!(rdr.read_u4()) + 1;
let mut floor0_book_list = Vec::with_capacity(
convert_to_usize!(floor0_number_of_books, u8));
for _ in 0 .. floor0_number_of_books {
let value = try!(rdr.read_u8());
if value as u16 > codebook_cnt {
try!(Err(HeaderReadError::HeaderBadFormat));
}
floor0_book_list.push(value);
}
Ok(Floor::TypeZero(FloorTypeZero {
floor0_order,
floor0_rate,
floor0_bark_map_size,
floor0_amplitude_bits,
floor0_amplitude_offset,
floor0_number_of_books,
floor0_book_list,
cached_bark_cos_omega : [
compute_bark_map_cos_omega(1 << (blocksizes.0 - 1),
floor0_rate, floor0_bark_map_size),
compute_bark_map_cos_omega(1 << (blocksizes.1 - 1),
floor0_rate, floor0_bark_map_size),
]
}))
},
1 => {
let floor1_partitions = try!(rdr.read_u5());
let mut maximum_class :i8 = -1;
let mut floor1_partition_class_list = Vec::with_capacity(
floor1_partitions as usize);
for _ in 0 .. floor1_partitions {
let cur_class = try!(rdr.read_u4());
maximum_class = if cur_class as i8 > maximum_class
{ cur_class as i8 } else { maximum_class };
floor1_partition_class_list.push(cur_class);
}
let mut floor1_class_dimensions = Vec::with_capacity((maximum_class + 1) as usize);
let mut floor1_class_subclasses = Vec::with_capacity((maximum_class + 1) as usize);
let mut floor1_subclass_books = Vec::with_capacity((maximum_class + 1) as usize);
let mut floor1_class_masterbooks = Vec::with_capacity((maximum_class + 1) as usize);
for _ in 0 .. maximum_class + 1 {
floor1_class_dimensions.push(try!(rdr.read_u3()) + 1);
let cur_subclass = try!(rdr.read_u2());
floor1_class_subclasses.push(cur_subclass);
if cur_subclass != 0 {
let cur_masterbook = try!(rdr.read_u8());
if cur_masterbook as u16 >= codebook_cnt {
try!(Err(HeaderReadError::HeaderBadFormat));
}
floor1_class_masterbooks.push(cur_masterbook);
} else {
floor1_class_masterbooks.push(0);
}
let cur_books_cnt :u8 = 1 << cur_subclass;
let mut cur_books = Vec::with_capacity(cur_books_cnt as usize);
for _ in 0 .. cur_books_cnt {
let cur_book = (try!(rdr.read_u8()) as i16) - 1;
if cur_book >= codebook_cnt as i16 {
try!(Err(HeaderReadError::HeaderBadFormat));
}
cur_books.push(cur_book);
}
floor1_subclass_books.push(cur_books);
}
let floor1_multiplier = try!(rdr.read_u2()) + 1;
let rangebits = try!(rdr.read_u4());
let mut floor1_values :u16 = 2;
for cur_class_num in &floor1_partition_class_list {
floor1_values += floor1_class_dimensions[*cur_class_num as usize] as u16;
}
if floor1_values > 65 {
try!(Err(HeaderReadError::HeaderBadFormat));
}
let mut floor1_x_list = Vec::with_capacity(floor1_values as usize);
floor1_x_list.push(0);
floor1_x_list.push(1u32 << rangebits);
for cur_class_num in &floor1_partition_class_list {
for _ in 0 .. floor1_class_dimensions[*cur_class_num as usize] {
floor1_x_list.push(try!(rdr.read_dyn_u32(rangebits)));
}
}
let mut floor1_x_list_sorted = floor1_x_list.iter().cloned()
.enumerate().collect::<Vec<_>>();
floor1_x_list_sorted.sort_by(|a, b| a.1.cmp(&b.1));
let mut last = 1;
for el in &floor1_x_list_sorted {
if el.1 == last {
try!(Err(HeaderReadError::HeaderBadFormat));
}
last = el.1;
}
Ok(Floor::TypeOne(FloorTypeOne {
floor1_multiplier,
floor1_partition_class : floor1_partition_class_list,
floor1_class_dimensions,
floor1_class_subclasses,
floor1_subclass_books,
floor1_class_masterbooks,
floor1_x_list,
floor1_x_list_sorted,
}))
},
_ => Err(HeaderReadError::HeaderBadFormat),
}
}
fn read_residue(rdr :&mut BitpackCursor, codebooks :&[Codebook])
-> Result<Residue, HeaderReadError> {
let residue_type = try!(rdr.read_u16());
if residue_type > 2 {
try!(Err(HeaderReadError::HeaderBadFormat));
}
let residue_begin = try!(rdr.read_u24());
let residue_end = try!(rdr.read_u24());
if residue_begin > residue_end {
try!(Err(HeaderReadError::HeaderBadFormat));
}
let residue_partition_size = try!(rdr.read_u24()) + 1;
let residue_classifications = try!(rdr.read_u6()) + 1;
let residue_classbook = try!(rdr.read_u8());
let mut residue_cascade = Vec::with_capacity(residue_classifications as usize);
for _ in 0 .. residue_classifications {
let mut high_bits = 0;
let low_bits = try!(rdr.read_u3());
let bitflag = try!(rdr.read_bit_flag());
if bitflag {
high_bits = try!(rdr.read_u5());
}
residue_cascade.push((high_bits << 3) | low_bits);
}
let mut residue_books = Vec::with_capacity(residue_classifications as usize);
for cascade_entry in &residue_cascade {
residue_books.push(try!(
ResidueBook::read_book(rdr, *cascade_entry, codebooks)));
}
if residue_classbook as usize >= codebooks.len() {
try!(Err(HeaderReadError::HeaderBadFormat));
}
return Ok(Residue {
residue_type : residue_type as u8,
residue_begin,
residue_end,
residue_partition_size,
residue_classifications,
residue_classbook,
residue_books,
});
}
fn read_mapping(rdr :&mut BitpackCursor,
audio_chan_ilog :u8, audio_channels :u8,
floor_count :u8, residue_count :u8)
-> Result<Mapping, HeaderReadError> {
let mapping_type = try!(rdr.read_u16());
if mapping_type > 0 {
try!(Err(HeaderReadError::HeaderBadFormat));
}
let mapping_submaps = match try!(rdr.read_bit_flag()) {
true => try!(rdr.read_u4()) + 1,
false => 1,
};
let mapping_coupling_steps = match try!(rdr.read_bit_flag()) {
true => try!(rdr.read_u8()) as u16 + 1,
false => 0,
};
let mut mapping_magnitudes = Vec::with_capacity(mapping_coupling_steps as usize);
let mut mapping_angles = Vec::with_capacity(mapping_coupling_steps as usize);
for _ in 0 .. mapping_coupling_steps {
let cur_mag = try!(rdr.read_dyn_u8(audio_chan_ilog));
let cur_angle = try!(rdr.read_dyn_u8(audio_chan_ilog));
if (cur_angle == cur_mag) || (cur_mag >= audio_channels)
|| (cur_angle >= audio_channels) {
try!(Err(HeaderReadError::HeaderBadFormat));
}
mapping_magnitudes.push(cur_mag);
mapping_angles.push(cur_angle);
}
let reserved = try!(rdr.read_u2());
if reserved != 0 {
try!(Err(HeaderReadError::HeaderBadFormat));
}
let mapping_mux = if mapping_submaps > 1 {
let mut m = Vec::with_capacity(audio_channels as usize);
for _ in 0 .. audio_channels {
let val = try!(rdr.read_u4());
if val >= mapping_submaps {
try!(Err(HeaderReadError::HeaderBadFormat));
}
m.push(val);
};
m
} else {
vec![0; audio_channels as usize]
};
let mut mapping_submap_floors = Vec::with_capacity(mapping_submaps as usize);
let mut mapping_submap_residues = Vec::with_capacity(mapping_submaps as usize);
for _ in 0 .. mapping_submaps {
try!(rdr.read_u8());
let cur_floor = try!(rdr.read_u8());
let cur_residue = try!(rdr.read_u8());
if cur_floor >= floor_count ||
cur_residue >= residue_count {
try!(Err(HeaderReadError::HeaderBadFormat));
}
mapping_submap_floors.push(cur_floor);
mapping_submap_residues.push(cur_residue);
}
return Ok(Mapping {
mapping_submaps,
mapping_magnitudes,
mapping_angles,
mapping_mux,
mapping_submap_floors,
mapping_submap_residues,
});
}
fn read_mode_info(rdr :&mut BitpackCursor, mapping_count :u8) -> Result<ModeInfo, HeaderReadError> {
let mode_blockflag = try!(rdr.read_bit_flag());
let mode_windowtype = try!(rdr.read_u16());
let mode_transformtype = try!(rdr.read_u16());
let mode_mapping = try!(rdr.read_u8());
if mode_windowtype != 0 ||
mode_transformtype != 0 ||
mode_mapping >= mapping_count {
try!(Err(HeaderReadError::HeaderBadFormat));
}
return Ok(ModeInfo {
mode_blockflag,
mode_mapping,
});
}
pub fn read_header_setup(packet :&[u8], audio_channels :u8, blocksizes :(u8, u8)) ->
Result<SetupHeader, HeaderReadError> {
let mut rdr = BitpackCursor::new(packet);
let hd_id = try!(read_header_begin(&mut rdr));
if hd_id != 5 {
try!(Err(HeaderReadError::HeaderBadType(hd_id)));
}
let audio_chan_ilog = ::ilog((audio_channels - 1) as u64);
let vorbis_codebook_count :u16 = try!(rdr.read_u8()) as u16 + 1;
let mut codebooks = Vec::with_capacity(vorbis_codebook_count as usize);
for _ in 0 .. vorbis_codebook_count {
codebooks.push(try!(read_codebook(&mut rdr)));
}
let vorbis_time_count :u8 = try!(rdr.read_u6()) + 1;
for _ in 0 .. vorbis_time_count {
if try!(rdr.read_u16()) != 0 {
try!(Err(HeaderReadError::HeaderBadFormat));
}
}
let vorbis_floor_count :u8 = try!(rdr.read_u6()) + 1;
let mut floors = Vec::with_capacity(vorbis_floor_count as usize);
for _ in 0 .. vorbis_floor_count {
floors.push(try!(read_floor(&mut rdr, vorbis_codebook_count, blocksizes)));
}
let vorbis_residue_count :u8 = try!(rdr.read_u6()) + 1;
let mut residues = Vec::with_capacity(vorbis_residue_count as usize);
for _ in 0 .. vorbis_residue_count {
residues.push(try!(read_residue(&mut rdr, &codebooks)));
}
let vorbis_mapping_count :u8 = try!(rdr.read_u6()) + 1;
let mut mappings = Vec::with_capacity(vorbis_mapping_count as usize);
for _ in 0 .. vorbis_mapping_count {
mappings.push(try!(read_mapping(& mut rdr,
audio_chan_ilog, audio_channels,
vorbis_floor_count, vorbis_residue_count)));
}
let vorbis_mode_count :u8 = try!(rdr.read_u6()) + 1;
let mut modes = Vec::with_capacity(vorbis_mode_count as usize);
for _ in 0 .. vorbis_mode_count {
modes.push(try!(read_mode_info(& mut rdr, vorbis_mapping_count)));
}
let framing :bool = try!(rdr.read_bit_flag());
if !framing {
try!(Err(HeaderReadError::HeaderBadFormat));
}
return Ok(SetupHeader {
codebooks,
floors,
residues,
mappings,
modes,
});
}