40 releases (21 stable)
2.6.0 | Nov 5, 2024 |
---|---|
2.5.0 | Jul 8, 2024 |
2.2.0 | Dec 12, 2023 |
1.10.0 | Nov 27, 2023 |
0.6.1 | Mar 27, 2017 |
#45 in Encoding
396,832 downloads per month
Used in 160 crates
(53 directly)
150KB
2.5K
SLoC
bitstream-io
A Rust library for reading or writing binary values to or from streams which may not be aligned at a whole byte.
This library is intended to be flexible enough to wrap
around any stream which implements the Read
or Write
traits.
It also supports a wide array of integer data types as
containers for those binary values.
Minimum Compiler Version
Beginning with version 2.4, the minimum compiler version has been
updated to Rust 1.79 in order to support compile-time assertion
in const
blocks, which can be used to check for a class
of errors at compile-time rather than runtime.
lib.rs
:
Traits and helpers for bitstream handling functionality
Bitstream readers are for reading signed and unsigned integer values from a stream whose sizes may not be whole bytes. Bitstream writers are for writing signed and unsigned integer values to a stream, also potentially un-aligned at a whole byte.
Both big-endian and little-endian streams are supported.
The only requirement for wrapped reader streams is that they must
implement the Read
trait, and the only requirement
for writer streams is that they must implement the Write
trait.
In addition, reader streams do not consume any more bytes from the underlying reader than necessary, buffering only a single partial byte as needed. Writer streams also write out all whole bytes as they are accumulated.
Readers and writers are also designed to work with integer types of any possible size. Many of Rust's built-in integer types are supported by default.
Minimum Compiler Version
Beginning with version 2.4, the minimum compiler version has been updated to Rust 1.79.
The issue is that reading an excessive number of bits to a type which is too small to hold them, or writing an excessive number of bits from too small of a type, are always errors:
use std::io::{Read, Cursor};
use bitstream_io::{BigEndian, BitReader, BitRead};
let data = [0; 10];
let mut r = BitReader::endian(Cursor::new(&data), BigEndian);
let x: Result<u32, _> = r.read(64); // reading 64 bits to u32 always fails at runtime
assert!(x.is_err());
but those errors will not be caught until the program runs, which is less than ideal for the common case in which the number of bits is already known at compile-time.
But starting with Rust 1.79, we can now have read and write methods which take a constant number of bits and can validate the number of bits are small enough for the type being read/written at compile-time:
use std::io::{Read, Cursor};
use bitstream_io::{BigEndian, BitReader, BitRead};
let data = [0; 10];
let mut r = BitReader::endian(Cursor::new(&data), BigEndian);
let x: Result<u32, _> = r.read_in::<64, _>(); // doesn't compile at all
Since catching potential bugs at compile-time is preferable to encountering errors at runtime, this will hopefully be an improvement in the long run.
Migrating From Pre 1.0.0
There are now BitRead
and BitWrite
traits for bitstream
reading and writing (analogous to the standard library's
Read
and Write
traits) which you will also need to import.
The upside to this approach is that library consumers
can now make functions and methods generic over any sort
of bit reader or bit writer, regardless of the underlying
stream byte source or endianness.