Trait bitstream_io::read::FromBitStreamWith
source · pub trait FromBitStreamWith {
type Context;
type Error;
// Required method
fn from_reader<R: BitRead + ?Sized>(
r: &mut R,
context: &Self::Context
) -> Result<Self, Self::Error>
where Self: Sized;
}
Expand description
Implemented by complex types that require some immutable context to parse themselves from a reader.
Example
use std::io::{Cursor, Read};
use bitstream_io::{BigEndian, BitRead, BitReader, FromBitStreamWith};
#[derive(Default)]
struct Streaminfo {
minimum_block_size: u16,
maximum_block_size: u16,
minimum_frame_size: u32,
maximum_frame_size: u32,
sample_rate: u32,
channels: u8,
bits_per_sample: u8,
total_samples: u64,
md5: [u8; 16],
}
#[derive(Debug, PartialEq, Eq)]
struct FrameHeader {
variable_block_size: bool,
block_size: u32,
sample_rate: u32,
channel_assignment: u8,
sample_size: u8,
frame_number: u64,
crc8: u8,
}
impl FromBitStreamWith for FrameHeader {
type Context = Streaminfo;
type Error = FrameHeaderError;
fn from_reader<R: BitRead + ?Sized>(
r: &mut R,
streaminfo: &Streaminfo,
) -> Result<Self, Self::Error> {
if r.read::<u16>(14)? != 0b11111111111110 {
return Err(FrameHeaderError::InvalidSync);
}
if r.read_bit()? != false {
return Err(FrameHeaderError::InvalidReservedBit);
}
let variable_block_size = r.read_bit()?;
let block_size_bits = r.read::<u8>(4)?;
let sample_rate_bits = r.read::<u8>(4)?;
let channel_assignment = r.read::<u8>(4)?;
let sample_size = match r.read::<u8>(3)? {
0b000 => streaminfo.bits_per_sample,
0b001 => 8,
0b010 => 12,
0b011 => return Err(FrameHeaderError::InvalidSampleSize),
0b100 => 16,
0b101 => 20,
0b110 => 24,
0b111 => 32,
_ => unreachable!(),
};
if r.read_bit()? != false {
return Err(FrameHeaderError::InvalidReservedBit);
}
let frame_number = read_utf8(r)?;
Ok(FrameHeader {
variable_block_size,
block_size: match block_size_bits {
0b0000 => return Err(FrameHeaderError::InvalidBlockSize),
0b0001 => 192,
n @ 0b010..=0b0101 => 576 * (1 << (n - 2)),
0b0110 => r.read::<u32>(8)? + 1,
0b0111 => r.read::<u32>(16)? + 1,
n @ 0b1000..=0b1111 => 256 * (1 << (n - 8)),
_ => unreachable!(),
},
sample_rate: match sample_rate_bits {
0b0000 => streaminfo.sample_rate,
0b0001 => 88200,
0b0010 => 176400,
0b0011 => 192000,
0b0100 => 8000,
0b0101 => 16000,
0b0110 => 22050,
0b0111 => 24000,
0b1000 => 32000,
0b1001 => 44100,
0b1010 => 48000,
0b1011 => 96000,
0b1100 => r.read::<u32>(8)? * 1000,
0b1101 => r.read::<u32>(16)?,
0b1110 => r.read::<u32>(16)? * 10,
0b1111 => return Err(FrameHeaderError::InvalidSampleRate),
_ => unreachable!(),
},
channel_assignment,
sample_size,
frame_number,
crc8: r.read(8)?
})
}
}
#[derive(Debug)]
enum FrameHeaderError {
Io(std::io::Error),
InvalidSync,
InvalidReservedBit,
InvalidSampleSize,
InvalidBlockSize,
InvalidSampleRate,
}
impl From<std::io::Error> for FrameHeaderError {
fn from(err: std::io::Error) -> Self {
Self::Io(err)
}
}
fn read_utf8<R: BitRead + ?Sized>(r: &mut R) -> Result<u64, std::io::Error> {
r.read(8) // left unimplimented in this example
}
let mut reader = BitReader::endian(Cursor::new(b"\xFF\xF8\xC9\x18\x00\xC2"), BigEndian);
assert_eq!(
reader.parse_with::<FrameHeader>(&Streaminfo::default()).unwrap(),
FrameHeader {
variable_block_size: false,
block_size: 4096,
sample_rate: 44100,
channel_assignment: 1,
sample_size: 16,
frame_number: 0,
crc8: 0xC2,
}
);