Module bitstream_io::read
source · Expand description
Traits and implementations for reading bits from a stream.
Example
Reading the initial STREAMINFO block from a FLAC file, as documented in its specification.
use std::io::{Cursor, Read};
use bitstream_io::{BigEndian, BitReader, BitRead, ByteReader, ByteRead, LittleEndian};
let flac: Vec<u8> = vec![0x66,0x4c,0x61,0x43,0x00,0x00,0x00,0x22,
0x10,0x00,0x10,0x00,0x00,0x06,0x06,0x00,
0x21,0x62,0x0a,0xc4,0x42,0xf0,0x00,0x04,
0xa6,0xcc,0xfa,0xf2,0x69,0x2f,0xfd,0xec,
0x2d,0x5b,0x30,0x01,0x76,0xb4,0x62,0x88,
0x7d,0x92,0x04,0x00,0x00,0x7a,0x20,0x00,
0x00,0x00,0x72,0x65,0x66,0x65,0x72,0x65,
0x6e,0x63,0x65,0x20,0x6c,0x69,0x62,0x46,
0x4c,0x41,0x43,0x20,0x31,0x2e,0x31,0x2e,
0x34,0x20,0x32,0x30,0x30,0x37,0x30,0x32,
0x31,0x33,0x04,0x00,0x00,0x00,0x16,0x00,
0x00,0x00,0x74,0x69,0x74,0x6c,0x65,0x3d,
0x32,0x63,0x68,0x20,0x34,0x34,0x31,0x30,
0x30,0x20,0x20,0x31,0x36,0x62,0x69,0x74,
0x10,0x00,0x00,0x00,0x61,0x6c,0x62,0x75,
0x6d,0x3d,0x54,0x65,0x73,0x74,0x20,0x41,
0x6c,0x62,0x75,0x6d,0x0f,0x00,0x00,0x00,
0x61,0x72,0x74,0x69,0x73,0x74,0x3d,0x41,
0x73,0x73,0x6f,0x72,0x74,0x65,0x64,0x0d,
0x00,0x00,0x00,0x74,0x72,0x61,0x63,0x6b,
0x6e,0x75,0x6d,0x62,0x65,0x72,0x3d,0x31];
#[derive(Debug, PartialEq, Eq)]
struct BlockHeader {
last_block: bool,
block_type: u8,
block_size: u32,
}
impl BlockHeader {
fn read<R: std::io::Read>(r: &mut BitReader<R, BigEndian>) -> std::io::Result<Self> {
Ok(Self {
last_block: r.read_bit()?,
block_type: r.read(7)?,
block_size: r.read(24)?,
})
}
}
#[derive(Debug, PartialEq, Eq)]
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],
}
impl Streaminfo {
fn read<R: std::io::Read>(r: &mut BitReader<R, BigEndian>) -> std::io::Result<Self> {
Ok(Self {
minimum_block_size: r.read(16)?,
maximum_block_size: r.read(16)?,
minimum_frame_size: r.read(24)?,
maximum_frame_size: r.read(24)?,
sample_rate: r.read(20)?,
channels: r.read::<u8>(3)? + 1,
bits_per_sample: r.read::<u8>(5)? + 1,
total_samples: r.read(36)?,
md5: r.read_to_bytes()?,
})
}
}
#[derive(Debug, PartialEq, Eq)]
struct VorbisComment {
vendor: String,
comment: Vec<String>,
}
impl VorbisComment {
fn read<R: std::io::Read>(
r: &mut ByteReader<R, LittleEndian>,
) -> Result<Self, Box<dyn std::error::Error>> {
fn read_entry<R: std::io::Read>(
r: &mut ByteReader<R, LittleEndian>,
) -> Result<String, Box<dyn std::error::Error>> {
use std::convert::TryInto;
let size = r.read::<u32>()?.try_into()?;
Ok(String::from_utf8(r.read_to_vec(size)?)?)
}
Ok(Self {
vendor: read_entry(r)?,
comment: (0..r.read::<u32>()?)
.map(|_| read_entry(r))
.collect::<Result<Vec<_>, _>>()?,
})
}
}
let mut cursor = Cursor::new(&flac);
let mut reader = BitReader::endian(&mut cursor, BigEndian);
// stream marker
assert_eq!(&reader.read_to_bytes().unwrap(), b"fLaC");
// metadata block header
assert_eq!(
BlockHeader::read(&mut reader).unwrap(),
BlockHeader { last_block: false, block_type: 0, block_size: 34 }
);
// STREAMINFO block
assert_eq!(
Streaminfo::read(&mut reader).unwrap(),
Streaminfo {
minimum_block_size: 4096,
maximum_block_size: 4096,
minimum_frame_size: 1542,
maximum_frame_size: 8546,
sample_rate: 44100,
channels: 2,
bits_per_sample: 16,
total_samples: 304844,
md5: *b"\xFA\xF2\x69\x2F\xFD\xEC\x2D\x5B\x30\x01\x76\xB4\x62\x88\x7D\x92",
}
);
// metadata block header
assert_eq!(
BlockHeader::read(&mut reader).unwrap(),
BlockHeader { last_block: false, block_type: 4, block_size: 122 }
);
// VORBIS_COMMENT block (little endian)
assert_eq!(
VorbisComment::read(&mut ByteReader::new(reader.reader().unwrap())).unwrap(),
VorbisComment {
vendor: "reference libFLAC 1.1.4 20070213".to_string(),
comment: vec![
"title=2ch 44100 16bit".to_string(),
"album=Test Album".to_string(),
"artist=Assorted".to_string(),
"tracknumber=1".to_string(),
],
}
);Structs
For reading non-aligned bits from a stream of bytes in a given endianness.
For reading aligned bytes from a stream of bytes in a given endianness.
Traits
A trait for anything that can read a variable number of
potentially un-aligned values from an input stream
A trait for anything that can read aligned values from an input stream
A trait for anything that can read Huffman codes
of a given endianness from an input stream