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,
    }
);

Required Associated Types§

source

type Context

Some context to use when parsing

source

type Error

Error generated during parsing, such as io::Error

Required Methods§

source

fn from_reader<R: BitRead + ?Sized>( r: &mut R, context: &Self::Context ) -> Result<Self, Self::Error>where Self: Sized,

Parse Self from reader with the given context

Implementors§