neobit
A zero-dependency, bitflags macro for systems programming. Designed for no_std environments.
Why neobit?
Bit operations are simple. The library should be too.
neobit provides union, intersection, difference, complement, and membership testing. Nothing more, nothing less.
Quick Start
use neobit;
neobit!
Features
- Zero dependencies - Pure Rust, nothing else
no_stdcompatible - Works in embedded environments- All integer types -
u8-u128andi8-i128 - Readable debug output -
Flags(READ | WRITE)instead ofFlags { bits: 3 } const fnoperations - Use in const contexts- Pure bitwise complement -
!flagsinverts all bits, not just known flags
Use Cases
- Hardware register manipulation
- Network protocol flags
- System call flags (C FFI)
- Embedded systems (
no_std) - Security-sensitive projects requiring easy code audit
Limitations
Composite Constants in Macro
Composite constants can be defined in the macro, but require using .union().bits() syntax:
neobit!
Alternatively, define composite constants outside the macro for cleaner syntax:
API Overview
Construction
empty // No flags set
all // All defined flags
from_bits // Validated, returns Option<Self>
from_bits_truncate // Truncate unknown bits
from_bits_retain // Keep all bits (for FFI)
Operations
flags.contains // All bits in other are in flags
flags.intersects // Any bits in other are in flags
flags.is_empty // No bits set
flags.is_all // All defined flags set
flags.bits // Raw bit value
Mutation
flags.insert // Add flags
flags.remove // Remove flags
flags.toggle // Flip flags
flags.set // Set or remove based on bool
Operators
| Operator | Meaning | const fn equivalent |
| |----------|---------|---------------------| |
| \| | Union | union() |
| & | Intersection | intersection() |
| ^ | Symmetric difference | symmetric_difference() |
| ! | Complement | complement() |
| - | Difference | difference() |
All operators have *Assign variants (|=, &=, etc.).
Const Context
const MASK: Flags = A.union;
const ALL: Flags = all;
Type Conversion
// From/Into (uses from_bits_retain)
let flags: Flags = 0b11.into;
let bits: u8 = flags.into;
// Explicit
let flags = from_bits_retain;
let bits = flags.bits;
Complement Behavior
neobit and bitflags implement complement() differently:
neobit!
let flags = A; // 0b00000001
// neobit: Pure bitwise NOT
let comp = !flags; // 0b11111110
// bitflags: Masked to known flags
// !flags -> 0b00000010
neobit preserves all bit information, which is essential for hardware registers and protocol handling.
Signed Types
Signed integers are supported for C FFI compatibility, but be careful with ! (complement):
neobit!
let complement = !A;
// i8: !0b0001 = -2 (two's complement)
// u8: !0b0001 = 254
// Prefer difference() for removing flags:
let all = all;
let without_a = all.difference;
C FFI Example
use neobit;
// Define flags matching a C header
neobit!
// Safe Rust wrapper around C functions
// See examples/c_ffi_simple.rs for a complete runnable example
Debug Output
Single-bit flags are shown by name. Composite constants are expanded:
println!; // Flags(READ)
println!; // Flags(READ | WRITE)
println!; // Flags(READ | WRITE | EXECUTE)
println!; // Flags(empty)
println!; // Flags(0x80)
Examples
Check out the examples/ directory for comprehensive demonstrations:
quick_start.rs- Basic usage with file permissionsall_method.rs- Using the built-inall()methodbit_validation.rs- Safe vs unchecked bit operationscomplement_difference.rs- How neobit differs from bitflagsoperators_and_methods.rs- All available operationstype_conversion.rs- Converting between integers and flagsc_ffi_simple.rs- C FFI and hardware register examplelimitations.rs- Macro limitations and workarounds
Run them with:
Minimum Rust Version
Rust 1.56 or later.
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT license (LICENSE-MIT)
at your option.