safebit

Crates.iosafebit
lib.rssafebit
version0.1.0
created_at2025-10-07 21:35:33.035929+00
updated_at2025-10-07 21:35:33.035929+00
descriptionSafe and secure bit access into integer types
homepage
repository
max_upload_size
id1872866
size34,277
Benedikt Radtke (Trolldemorted)

documentation

README

safebit Crates.io

safebit provides a simple interface to bit slices of integers.

It is designed to fulfill the following goals:

  • No dependencies: Every dependency is a security and reliability risk. safebit is simple enough to not need any dependencies.

  • No unsafe code: Safety and security are more important than performance.

  • No panics: While panics usually have no security impact, they can have a significant impact on safety. safebit must not panic during any operation on any of safebit's types.

  • no std and alloc: All basic operations work without std and alloc. Glue code for common std types is gated by the std feature.

Examples

Bitstream

extern crate std;
use safebit::{bitstream::Bitstream, util::LittleEndian};

// Blanket implementation for Read is provided if the std feature is enabled
let mut f = std::fs::File::open("Cargo.toml").unwrap();
let mut stream: Bitstream<u16, _, _, LittleEndian> = Bitstream::new(&mut f);

// Read the first few nibbles of "[package]"
let n0: u16 = stream.read(4).unwrap();
assert_eq!(n0, 0b0111);
let n1: u16 = stream.read(4).unwrap();
assert_eq!(n1, 0b0000);
let n2: u16 = stream.read(4).unwrap();
assert_eq!(n2, 0b0101);
let n3: u16 = stream.read(4).unwrap();
assert_eq!(n3, 0b1011);

// The bitstream constructor accepts references to everything that implements read, such as
// BufReader. If you need a custom reader, you can implement your own.
let mut buf_reader = std::io::BufReader::new(f);
let mut stream2: Bitstream<u16, _, _, LittleEndian> = Bitstream::new(&mut buf_reader);
let n4: i16 = stream2.read(4).unwrap();
assert_eq!(n4, 0b0110);
let n5: i16 = stream2.read(4).unwrap();
assert_eq!(n5, 0b0011);
let zero: u16 = stream2.read(1).unwrap();
assert_eq!(zero, 0b0);
let signed: i16 = stream2.read(3).unwrap(); // 0b110
assert_eq!(signed, -2);

Cursor

use safebit::error::CursorError;
use safebit::word_read::Cursor;
use safebit::word_read::WordRead;

let data: [u16; 4] = [1, 2, 3, 4];
let mut cursor = Cursor::new(&data);
assert_eq!(cursor.read().unwrap(), 1);
assert_eq!(cursor.read().unwrap(), 2);
assert_eq!(cursor.read().unwrap(), 3);
assert_eq!(cursor.read().unwrap(), 4);
assert_eq!(cursor.read(), Err(CursorError::EndOfCursor));

Words

use safebit::word::Word;
use safebit::error::WordError;

let t0: u16 = 0xff00;
let t1: u8 = 0b0000_0010;

// Extract a slice from an u16 into an u8
assert_eq!(t0.get::<u8>(4..12).unwrap(), 0xf0);

// Extract a slice into an u8 which does not fit
assert_eq!(t0.get::<u8>(0..9), Err(WordError::InvalidBounds));

// Extract a slice with the most significant bit set into a signed type
assert_eq!(t1.get::<i16>(0..2), Ok(-2));
Commit count: 0

cargo fmt