| Crates.io | oot_bitset |
| lib.rs | oot_bitset |
| version | 0.1.1 |
| created_at | 2025-07-04 19:42:26.880731+00 |
| updated_at | 2025-07-04 19:44:28.657303+00 |
| description | A no‑frills, zero‑overhead bit flag system |
| homepage | |
| repository | https://github.com/jb55/oot_bitset |
| max_upload_size | |
| id | 1738408 |
| size | 13,972 |
A no‑frills, zero‑overhead flag system inspired by The Legend of Zelda: Ocarina of Time
Implemented in C / C++, and Rust
Need to pack hundreds (or thousands) of one‑bit flags—“talked to an NPC”, “opened a chest”, etc.—into a save file without wasting bytes? Ocarina of Time solved this by storing flags in an array of uint16_t words. oot_bitset offers the same trick in either language, with zero runtime overhead.
u16 word ≙ 16 flags. Scale from 1 to 4096 words (65 536 flags).alloc.oot_bitset.h somewhere in your include path.cc -std=c99 my_game.c -o my_game
Add the crate to your Cargo.toml:
[dependencies]
oot_bitset = "0.1"
#include "oot_bitset.h"
#include <stdio.h>
enum GameEvents {
FLAG_MET_RUTO_FIRST_TIME = 0x00, // word 0, bit 0
FLAG_TALKED_TO_MALON_FIRST_TIME = 0x02, // word 0, bit 2
FLAG_SAW_BOB = 0x10, // word 1, bit 0
FLAG_SAW_ALICE = 0x1A // word 1, bit 10
};
int main(void) {
uint16_t flags[30] = {0}; // 30 words ⇒ 480 flags
bitset_set(flags, FLAG_SAW_BOB);
printf("Saw Bob? %s\n", bitset_get(flags, FLAG_SAW_BOB) ? "yes" : "no");
}
Compile:
cc -std=c99 demo.c -o demo
use oot_bitset::{bitset_get, bitset_set};
#[repr(u16)]
enum GameEvents {
MetRutoFirstTime = 0x00, // word 0, bit 0
TalkedToMalonFirstTime = 0x02, // word 0, bit 2
SawBob = 0x10, // word 1, bit 0
SawAlice = 0x1A, // word 1, bit 10
}
fn main() {
let mut flags = [0u16; 30]; // 30 words ⇒ 480 flags
bitset_set(&mut flags, GameEvents::SawBob as u16);
println!("Saw Bob? {}", bitset_get(&flags, GameEvents::SawBob as u16));
}
Run:
cargo run --example basic
#define bitset_word(set, flag) ((set)[bitset_index(flag)])
static inline uint16_t bitset_index(uint16_t flag); // word (0–4095)
static inline uint16_t bitset_mask(uint16_t flag); // bit (0–15)
static inline bool bitset_get (uint16_t *set, uint16_t flag);
static inline void bitset_set (uint16_t *set, uint16_t flag);
static inline void bitset_clear(uint16_t *set, uint16_t flag);
pub const fn bitset_index(flag: u16) -> usize;
pub const fn bitset_mask(flag: u16) -> u16;
pub fn bitset_get (set: &[u16], flag: u16) -> bool;
pub fn bitset_set (set: &mut [u16], flag: u16);
pub fn bitset_clear(set: &mut [u16], flag: u16);
pub fn bitset_word_mut(set: &mut [u16], flag: u16) -> &mut u16;
All functions are #[inline(always)] and panic if the slice is too short.
max_flags = words × 16
words = ceil(max_flags / 16)
Use as few or as many words as your project needs. OoT used 30 words (480 flags), but nothing stops you from using 1 word (16 flags) or 4 096 words (65 536 flags).
| Bits | 15…4 (12 bits) | 3…0 (4 bits) |
|---|---|---|
| Use | word index | bit index |
| Max | 0–4095 words | 0–15 bits |
Because each hex digit is 4 bits, you can read a flag as “word:bit”.
Example: 0x1AC → word 26, bit 12.
Words[0] = 0x0004 // FLAG_TALKED_TO_MALON_FIRST_TIME
Words[1] = 0x0401 // FLAG_SAW_BOB | FLAG_SAW_ALICE