3 releases
0.1.2 | Aug 2, 2022 |
---|---|
0.1.1 | Jul 27, 2022 |
0.1.0 | Jul 27, 2022 |
#7 in #bit-level
16KB
125 lines
bit_buffers
The bit_buffers
library allows for the reading and writing of individual bits to and from files.
This library offers prototype versions of a bit reading entity and a bit writing entity that both keep track of how many bits are contained within them, and at which bit they are currently using.
Example Usage (writing bits to a file)
If you want to save a sequence of bits to a file, use a BitWriter.
// main.rs
use bit_buffers::BitWriter;
fn main() {
// Create the writer
let mut bit_writer = BitWriter::new();
// Write out the desired bits
bit_writer.write_bit(1);
bit_writer.write_bit(0);
bit_writer.write_bit(1);
bit_writer.write_bit(1);
bit_writer.write_bit(1);
bit_writer.write_bit(1);
bit_writer.write_bit(0);
bit_writer.write_bit(1);
// Save the bits to a file and clear out this writer
bit_writer.flush_to_file("bit_sequence.bit");
}
Example Usage (reading bits from a file)
Later, if you want to read those same bits back in the order in which they were written, use a BitReader. A BitReader returns each bit in an Option, allowing the reader to return None after the last bit was read.
// main.rs
use bit_buffers::BitReader;
fn main() {
// Load bits in from the file
let mut bit_reader = BitReader::new();
bit_reader.load_from_file("bit_sequence.bit");
// Read those bits in from the file
let bit_1_option = bit_reader.read_bit();
let bit_2_option = bit_reader.read_bit();
let bit_3_option = bit_reader.read_bit();
let bit_4_option = bit_reader.read_bit();
let bit_5_option = bit_reader.read_bit();
let bit_6_option = bit_reader.read_bit();
let bit_7_option = bit_reader.read_bit();
let bit_8_option = bit_reader.read_bit();
// After the last bit, None is returned
let bit_9_option = bit_reader.read_bit();
// Try and print the 9th bit
if let Some(_) = bit_9_option {
println!("There might still be more!");
} else {
println!("All bits were read in from the file!");
}
}
Binary File Format
A simple format is used to write out bits to a file:
- number of bits
- bit data
Under the hood, a u128 type variable is used to count the number of bits in the file. As far as byte ordering is concerned, endianness is determined by the user's system.
When writing out the actual bit data, there may be atmost 7 extra bits of padding that are not included in the count.
When using a BitReader, it is best to use a file generated by a BitWriter, unless you are comfortable writing a file with the correct format describing the information you want.
Example Bit File
Consider the example program above demonstrating the use of a BitWriter. After a call to bit_writer.flush_to_file("bit_sequence.bit")
, the following binary file is produced.
08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 BD
When viewed in a hex editor, that binary file may appear like this.
00000000 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000010 BD
Future Goals
- Thread Safety
As of now, this library has not been tested in a multi-threaded application. Neither BitReader nor BitWriter are guaranteed to be thread safe at this time.
- Sharability
When reading and writing bits from and to files, the user's system determines the endianness. This may lead to problems when trying to share bit files across a network. A future goal is to standardize how the number of bits are written to and read from such files.
- Optimization
When bits are written to a BitWriter, they are written directly to an internal vector of bytes. The code as of now is messy and error-prone. Adding an additional buffer may simplify the underlying logic.
Additionally, for every 8 bits of data written, a re-allocation may need to take place. Adding features to allow users to reserve an expected amount of space may amortize the cost of reading and writing bits over time.
- Additional Features
Currently, there is no way for a user to index into the buffer to read specific bits or overwrite bits.