1 unstable release
| 0.1.0 | Oct 7, 2025 |
|---|
#2131 in Rust patterns
26KB
596 lines
safebit 
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.
safebitis 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.
safebitmust not panic during any operation on any ofsafebit's types. - no std and alloc: All basic operations work without std and alloc. Glue code for common std types is gated by the
stdfeature.
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));