BitWriter

Trait BitWriter 

Source
pub trait BitWriter {
Show 16 methods // Required methods fn write_bit(&mut self, bit: bool) -> Result<()>; fn write_u8(&mut self, value: u8) -> Result<()>; fn write_i8(&mut self, value: i8) -> Result<()>; fn write_u16(&mut self, value: u16) -> Result<()>; fn write_i16(&mut self, value: i16) -> Result<()>; fn write_u32(&mut self, value: u32) -> Result<()>; fn write_i32(&mut self, value: i32) -> Result<()>; fn write_f32(&mut self, value: f32) -> Result<()>; fn write_u64(&mut self, value: u64) -> Result<()>; fn write_i64(&mut self, value: i64) -> Result<()>; fn write_f64(&mut self, value: f64) -> Result<()>; fn write_bits(&mut self, bits: u32, value: u64) -> Result<()>; fn write_signed_bits(&mut self, bits: u32, value: i64) -> Result<()>; fn unaligned_bits(&self) -> u32; fn write_bytes(&mut self, buf: &[u8]) -> Result<()>; fn flush(&mut self) -> Result<()>;
}
Expand description

Write bits in a given endian order

The BitWriter trait provides methods for writing data bit-by-bit to any type that implements std::io::Write. It supports writing individual bits, standard data types (integers, floats), and arbitrary bit sequences.

§Examples

use bitter::{BitWriter, LittleEndianWriter};

let mut buffer = Vec::new();
let mut writer = LittleEndianWriter::new(&mut buffer);

writer.write_bit(true).unwrap();
writer.write_u8(0xff).unwrap();
writer.write_bits(4, 0xA).unwrap();
writer.flush().unwrap();

Required Methods§

Source

fn write_bit(&mut self, bit: bool) -> Result<()>

Write a single bit

§Examples
use bitter::{BitWriter, LittleEndianWriter};

let mut buffer = Vec::new();
{
    let mut writer = LittleEndianWriter::new(&mut buffer);
    writer.write_bit(true).unwrap();
    writer.write_bit(false).unwrap();
    writer.flush().unwrap();
}

assert_eq!(buffer, &[0b01]);
Source

fn write_u8(&mut self, value: u8) -> Result<()>

Write 8 bits as a byte

§Examples
use bitter::{BitWriter, LittleEndianWriter};

let mut buffer = Vec::new();
{
    let mut writer = LittleEndianWriter::new(&mut buffer);
    writer.write_u8(0xAB).unwrap();
    writer.flush().unwrap();
}

assert_eq!(buffer, &[0xAB]);
Source

fn write_i8(&mut self, value: i8) -> Result<()>

Write 8 bits as a signed byte

§Examples
use bitter::{BitWriter, LittleEndianWriter};

let mut buffer = Vec::new();
{
    let mut writer = LittleEndianWriter::new(&mut buffer);
    writer.write_i8(-42).unwrap();
    writer.flush().unwrap();
}

assert_eq!(buffer, &[(-42i8) as u8]);
Source

fn write_u16(&mut self, value: u16) -> Result<()>

Write 16 bits as an unsigned short

§Examples
use bitter::{BitWriter, LittleEndianWriter};

let mut buffer = Vec::new();
{
    let mut writer = LittleEndianWriter::new(&mut buffer);
    writer.write_u16(0x1234).unwrap();
    writer.flush().unwrap();
}

// Little endian: least significant byte first
assert_eq!(buffer, &[0x34, 0x12]);
Source

fn write_i16(&mut self, value: i16) -> Result<()>

Write 16 bits as a signed short

§Examples
use bitter::{BitWriter, BigEndianWriter};

let mut buffer = Vec::new();
{
    let mut writer = BigEndianWriter::new(&mut buffer);
    writer.write_i16(-1000).unwrap();
    writer.flush().unwrap();
}

// Big endian: most significant byte first
let expected = (-1000i16).to_be_bytes();
assert_eq!(buffer, expected.as_slice());
Source

fn write_u32(&mut self, value: u32) -> Result<()>

Write 32 bits as an unsigned int

§Examples
use bitter::{BitWriter, LittleEndianWriter};

let mut buffer = Vec::new();
{
    let mut writer = LittleEndianWriter::new(&mut buffer);
    writer.write_u32(0xDEADBEEF).unwrap();
    writer.flush().unwrap();
}

assert_eq!(buffer, &[0xEF, 0xBE, 0xAD, 0xDE]);
Source

fn write_i32(&mut self, value: i32) -> Result<()>

Write 32 bits as a signed int

§Examples
use bitter::{BitWriter, LittleEndianWriter};

let mut buffer = Vec::new();
{
    let mut writer = LittleEndianWriter::new(&mut buffer);
    writer.write_i32(-123456).unwrap();
    writer.flush().unwrap();
}

let expected = (-123456i32).to_le_bytes();
assert_eq!(buffer, expected.as_slice());
Source

fn write_f32(&mut self, value: f32) -> Result<()>

Write 32 bits as a floating point

§Examples
use bitter::{BitWriter, LittleEndianWriter};

let mut buffer = Vec::new();
{
    let mut writer = LittleEndianWriter::new(&mut buffer);
    writer.write_f32(3.14159).unwrap();
    writer.flush().unwrap();
}

let expected = 3.14159f32.to_le_bytes();
assert_eq!(buffer, expected.as_slice());
Source

fn write_u64(&mut self, value: u64) -> Result<()>

Write 64 bits as an unsigned long

§Examples
use bitter::{BitWriter, BigEndianWriter};

let mut buffer = Vec::new();
{
    let mut writer = BigEndianWriter::new(&mut buffer);
    writer.write_u64(0x123456789ABCDEF0).unwrap();
    writer.flush().unwrap();
}

let expected = 0x123456789ABCDEF0u64.to_be_bytes();
assert_eq!(buffer, expected.as_slice());
Source

fn write_i64(&mut self, value: i64) -> Result<()>

Write 64 bits as a signed long

§Examples
use bitter::{BitWriter, LittleEndianWriter};

let mut buffer = Vec::new();
{
    let mut writer = LittleEndianWriter::new(&mut buffer);
    writer.write_i64(-9876543210).unwrap();
    writer.flush().unwrap();
}

let expected = (-9876543210i64).to_le_bytes();
assert_eq!(buffer, expected.as_slice());
Source

fn write_f64(&mut self, value: f64) -> Result<()>

Write 64 bits as a floating point

§Examples
use bitter::{BitWriter, LittleEndianWriter};

let mut buffer = Vec::new();
{
    let mut writer = LittleEndianWriter::new(&mut buffer);
    writer.write_f64(2.718281828459045).unwrap();
    writer.flush().unwrap();
}

let expected = 2.718281828459045f64.to_le_bytes();
assert_eq!(buffer, expected.as_slice());
Source

fn write_bits(&mut self, bits: u32, value: u64) -> Result<()>

Write an arbitrary number of bits (up to and including 64) as unsigned value

§Examples
use bitter::{BitWriter, LittleEndianWriter};

let mut buffer = Vec::new();
{
    let mut writer = LittleEndianWriter::new(&mut buffer);
     
    // Write 12 bits with value 0xABC
    writer.write_bits(12, 0xABC).unwrap();
    writer.flush().unwrap();
}

// 0xABC = 2748 = 1010 1011 1100 in binary
// In little endian, this gets packed as: [0xBC, 0x0A]
assert_eq!(buffer, &[0xBC, 0x0A]);
Source

fn write_signed_bits(&mut self, bits: u32, value: i64) -> Result<()>

Write an arbitrary number of bits (up to and including 64) as signed value

The value is sign-extended or truncated to fit the specified number of bits.

§Examples
use bitter::{BitWriter, LittleEndianWriter};

let mut buffer = Vec::new();
{
    let mut writer = LittleEndianWriter::new(&mut buffer);
     
    // Write -3 in 4 bits (will be 0b1101 in two's complement)
    writer.write_signed_bits(4, -3).unwrap();
    writer.flush().unwrap();
}

// -3 in 4 bits = 0b1101, padded with zeros to complete the byte
assert_eq!(buffer, &[0x0D]); // 0b0000_1101
Source

fn unaligned_bits(&self) -> u32

Returns the number of bits written in the current partial byte

When the writer is byte-aligned, this returns 0. Otherwise, it returns the number of bits (1-7) already written in the current byte.

§Examples
use bitter::{BitWriter, LittleEndianWriter};

let mut buffer = Vec::new();
let mut writer = LittleEndianWriter::new(&mut buffer);

assert_eq!(writer.unaligned_bits(), 0); // Byte-aligned

writer.write_bit(true).unwrap();
assert_eq!(writer.unaligned_bits(), 1); // 1 bit in current byte

writer.write_bits(7, 0x7F).unwrap();
assert_eq!(writer.unaligned_bits(), 0); // Aligned again (1+7=8)
Source

fn write_bytes(&mut self, buf: &[u8]) -> Result<()>

Write the provided buffer as bytes

This method writes the entire buffer as a sequence of bytes. If the writer is not currently byte-aligned, the bytes will be written starting from the current bit position, potentially spanning across byte boundaries.

§Examples
use bitter::{BitWriter, LittleEndianWriter};

let mut buffer = Vec::new();
{
    let mut writer = LittleEndianWriter::new(&mut buffer);

    // Write some bytes
    let data = [0xAB, 0xCD, 0xEF];
    writer.write_bytes(&data).unwrap();
    writer.flush().unwrap();
}

assert_eq!(buffer, &[0xAB, 0xCD, 0xEF]);
§Byte Alignment

When not byte-aligned, bytes are written bit by bit:

use bitter::{BitWriter, LittleEndianWriter};

let mut buffer = Vec::new();
{
    let mut writer = LittleEndianWriter::new(&mut buffer);

    writer.write_bit(true).unwrap();  // Not byte-aligned
    writer.write_bytes(&[0xFF]).unwrap();
    writer.flush().unwrap();
}

// The 0xFF byte gets shifted due to the initial bit
assert_eq!(buffer, &[0xFF, 0x01]);  // 0xFF shifted + remaining bit
Source

fn flush(&mut self) -> Result<()>

Flush any buffered bits, padding with zeros if necessary

This method ensures all pending bits are written to the underlying writer. If there are partial bits remaining, they are zero-padded to complete the current byte.

§Zero Padding Behavior

Important: When flushing partial bytes, the remaining bits are always padded with zeros. This behavior can affect data interpretation if you’re not expecting it:

  • Little-endian: Zero bits are added to the high-order positions
  • Big-endian: Zero bits are added to the low-order positions
§Examples
use bitter::{BitWriter, LittleEndianWriter};

let mut buffer = Vec::new();
{
    let mut writer = LittleEndianWriter::new(&mut buffer);
    writer.write_bits(3, 0b101).unwrap(); // Write 3 bits
    // Buffer is still empty until we flush
    writer.flush().unwrap(); // Force write with zero padding
}

assert_eq!(buffer.len(), 1);
assert_eq!(buffer[0], 0b00000101); // 3 bits + 5 zero-padded bits

For big-endian, padding appears in different positions:

use bitter::{BitWriter, BigEndianWriter};

let mut buffer = Vec::new();
{
    let mut writer = BigEndianWriter::new(&mut buffer);
    writer.write_bits(3, 0b101).unwrap(); // Write 3 bits  
    writer.flush().unwrap(); // Force write with zero padding
}

assert_eq!(buffer.len(), 1);
assert_eq!(buffer[0], 0b10100000); // 3 bits + 5 zero-padded bits

Implementors§