{"id":13595340,"url":"https://github.com/ferrilab/bitvec","last_synced_at":"2026-01-15T22:20:19.361Z","repository":{"id":36989503,"uuid":"138975689","full_name":"ferrilab/bitvec","owner":"ferrilab","description":"A crate for managing memory bit by bit","archived":false,"fork":false,"pushed_at":"2024-08-09T07:35:32.000Z","size":4311,"stargazers_count":1292,"open_issues_count":92,"forks_count":121,"subscribers_count":11,"default_branch":"main","last_synced_at":"2025-05-08T19:03:51.785Z","etag":null,"topics":["bitset","bitvector","rust"],"latest_commit_sha":null,"homepage":"https://myrrlyn.net/crates/bitvec","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ferrilab.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":"AUTHORS.txt","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-06-28T06:26:44.000Z","updated_at":"2025-05-08T15:30:41.000Z","dependencies_parsed_at":"2024-11-05T18:03:20.203Z","dependency_job_id":"060c6f56-f1a0-4c59-8a65-815ef97f784a","html_url":"https://github.com/ferrilab/bitvec","commit_stats":{"total_commits":537,"total_committers":35,"mean_commits":"15.342857142857143","dds":0.0912476722532588,"last_synced_commit":"5fb855073acc2ed045094ed89d8daf8c765f0135"},"previous_names":["bitvecto-rs/bitvec","myrrlyn/bitvec"],"tags_count":42,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ferrilab%2Fbitvec","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ferrilab%2Fbitvec/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ferrilab%2Fbitvec/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ferrilab%2Fbitvec/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ferrilab","download_url":"https://codeload.github.com/ferrilab/bitvec/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254036831,"owners_count":22003654,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bitset","bitvector","rust"],"created_at":"2024-08-01T16:01:48.089Z","updated_at":"2025-12-12T16:56:34.906Z","avatar_url":"https://github.com/ferrilab.png","language":"Rust","readme":"\u003cdiv style=\"text-align: center;\" align=\"center\"\u003e\n\n# `bitvec`\n\n## A Magnifying Glass for Memory \u003c!-- omit in toc --\u003e\n\n[![Crate][crate_img]][crate_link]\n[![MSRV][msrv_img]][crate_link]\n[![License][license_img]][license_file]\n\n[![Documentation][docs_img]][docs_link]\n[![Crate Downloads][downloads_img]][crate_link]\n\n\u003c/div\u003e\n\n1. [Summary](#summary)\n1. [Introduction](#introduction)\n1. [Highlights](#highlights)\n1. [Usage](#usage)\n1. [Examples](#examples)\n1. [User Stories](#user-stories)\n   1. [Bit Collections](#bit-collections)\n   1. [Bit-Field Memory Access](#bit-field-memory-access)\n   1. [Transport Protocols](#transport-protocols)\n1. [Feature Flags](#feature-flags)\n1. [Deeper Reading](#deeper-reading)\n\n## Summary\n\n`bitvec` provides a foundational API for bitfields in Rust. It specializes\nstandard-library data structures (slices, arrays, and vectors of `bool`) to use\none-bit-per-`bool` storage, similar to [`std::bitset\u003cN\u003e`] and\n[`std::vector\u003cbool\u003e`] in C++.\n\nAdditionally, it allows a memory region to be divided into arbitrary regions of\ninteger storage, like [binaries][erl_bit] in Erlang.\n\nIf you need to view memory as bit-addressed instead of byte-addressed, then\n`bitvec` is the most capable, complete, and Rust-idiomatic crate for you.\n\n## Introduction\n\nComputers do not operate on bits. The memory bus is byte-addressed, and\nprocessors operate on register words, which are typically four to eight bytes,\nor even wider. This means that when programmers wish to operate on individual\nbits within a byte of memory or a word of register, they have to do so manually,\nusing shift and mask operations that are likely familiar to anyone who has done\nthis before.\n\n`bitvec` brings the capabilities of C++’s compact `bool` storage and Erlang’s\ndecomposable bit-streams to Rust, in a package that fits in with your existing\nRust idioms and in the most capable, performant, implementation possible. The\nbit-stream behavior provides the logic necessary for C-style structural\nbitfields, and syntax sugar for it can be found in [`deku`].\n\n`bitvec` enables you to write code for bit-addressed memory that is simple,\neasy, and fast. It compiles to the same, or even better, object code than you\nwould get from writing shift/mask instructions manually. It leverages Rust’s\npowerful reference and type systems to create a system that seamlessly bridges\nsingle-bit addressing, precise control of in-memory layout, and Rust-native\nownership and borrowing mechanisms.\n\n## Highlights\n\n`bitvec` has a number of unique capabilities related to its place as a Rust\nlibrary and as a bit-addressing system.\n\n- It supports arbitrary bit-addressing, and its bit slices can be munched from\n  the front.\n- `BitSlice` is a region type equivalent to `[bool]`, and can be described by\n  Rust references and thus fit into reference-based APIs.\n- Type parameters enable users to select the precise memory representation they\n  desire.\n- A memory model accounts for element-level aliasing and is safe for concurrent\n  use. In particular, the “Beware Bitfields” bug described in\n  [this Mozilla report][moz] is simply impossible to produce.\n- Native support for atomic integers as bit-field storage.\n- Users can supply their own translation layer for memory representation if the\n  built-in translations are insufficient.\n\nHowever, it does also have some small costs associated with its capabilities:\n\n- `BitSlice` cannot be used as a referent type in pointers, such as `Box`, `Rc`,\n  or `Arc`.\n- `BitSlice` cannot implement `IndexMut`, so `bitslice[index] = true;` does not\n  work.\n\n## Usage\n\n`bitvec` strives to follow the sequence APIs in the standard library. However,\nas most of its functionality is a reïmplementation that does not require the\nstandard library to actually have the symbols present, doing so may not require\nan MSRV raise.\n\nNow that `bitvec` is at 1.0, it will only raise MSRV in minor-edition releases.\nIf you have a pinned Rust toolchain, you should depend on `bitvec` with a\nlimiting minor-version constraint like `\"~1.0\"`.\n\nFirst, depend on it in your Cargo manifest:\n\n```toml\n[dependencies]\nbitvec = \"1\"\n```\n\n\u003e Note: `bitvec` supports `#![no_std]` targets. If you do not have `std`,\n\u003e disable the default features, and explicitly restore any features that you do\n\u003e have:\n\u003e\n\u003e ```toml\n\u003e [dependencies.bitvec]\n\u003e version = \"1\"\n\u003e default-features = false\n\u003e features = [\"atomic\", \"alloc\"]\n\u003e ```\n\nOnce Cargo knows about it, bring its prelude into scope:\n\n```rust\nuse bitvec::prelude::*;\n```\n\nYou can read the [prelude reëxports][prelude] to see exactly which symbols are\nbeing imported. The prelude brings in many symbols, and while name collisions\nare not likely, you may wish to instead import the prelude *module* rather than\nits contents:\n\n```rust\nuse bitvec::prelude as bv;\n```\n\nYou should almost certainly use type aliases to make names for specific\ninstantiations of `bitvec` type parameters, and use that rather than attempting\nto remain generic over an `\u003cT: BitStore, O: BitOrder\u003e` pair throughout your\nproject.\n\n## Examples\n\n```rust\nuse bitvec::prelude::*;\n\n// All data-types have macro\n// constructors.\nlet arr = bitarr![u32, Lsb0; 0; 80];\nlet bits = bits![u16, Msb0; 0; 40];\n\n// Unsigned integers (scalar, array,\n// and slice) can be borrowed.\nlet data = 0x2021u16;\nlet bits = data.view_bits::\u003cMsb0\u003e();\nlet data = [0xA5u8, 0x3C];\nlet bits = data.view_bits::\u003cLsb0\u003e();\n\n// Bit-slices can split anywhere.\nlet (head, rest) = bits.split_at(4);\nassert_eq!(head, bits[.. 4]);\nassert_eq!(rest, bits[4 ..]);\n\n// And they are writable!\nlet mut data = [0u8; 2];\nlet bits = data.view_bits_mut::\u003cLsb0\u003e();\n// l and r each own one byte.\nlet (l, r) = bits.split_at_mut(8);\n\n// but now a, b, c, and d own a nibble!\nlet ((a, b), (c, d)) = (\n  l.split_at_mut(4),\n  r.split_at_mut(4),\n);\n\n// and all four of them are writable.\na.set(0, true);\nb.set(1, true);\nc.set(2, true);\nd.set(3, true);\n\nassert!(bits[0]);  // a[0]\nassert!(bits[5]);  // b[1]\nassert!(bits[10]); // c[2]\nassert!(bits[15]); // d[3]\n\n// `BitSlice` is accessed by reference,\n// which means it respects NLL styles.\nassert_eq!(data, [0x21u8, 0x84]);\n\n// Furthermore, bit-slices can store\n// ordinary integers:\nlet eight = [0u8, 4, 8, 12, 16, 20, 24, 28];\n//           a    b  c  d   e   f   g   h\nlet mut five = [0u8; 5];\nfor (slot, byte) in five\n  .view_bits_mut::\u003cMsb0\u003e()\n  .chunks_mut(5)\n  .zip(eight.iter().copied())\n{\n  slot.store_be(byte);\n  assert_eq!(slot.load_be::\u003cu8\u003e(), byte);\n}\n\nassert_eq!(five, [\n  0b00000_001,\n//  aaaaa bbb\n  0b00_01000_0,\n//  bb ccccc d\n  0b1100_1000,\n//  dddd eeee\n  0b0_10100_11,\n//  e fffff gg\n  0b000_11100,\n//  ggg hhhhh\n]);\n```\n\nThe `BitSlice` type is a view that alters the behavior of a borrowed memory\nregion. It is never held directly, but only by references (created by borrowing\ninteger memory) or the `BitArray` value type. In addition, the presence of a\ndynamic allocator enables the `BitBox` and `BitVec` buffer types, which can be\nused for more advanced buffer manipulation:\n\n```rust\n#[cfg(feature = \"alloc\")]\nfn main() {\n\nuse bitvec::prelude::*;\n\nlet mut bv = bitvec![u8, Msb0;];\nbv.push(false);\nbv.push(true);\nbv.extend([false; 4].iter());\nbv.extend(\u002615u8.view_bits::\u003cLsb0\u003e()[.. 4]);\n\nassert_eq!(bv.as_raw_slice(), \u0026[\n  0b01_0000_11, 0b11_000000\n//                   ^ dead\n]);\n\n}\n```\n\nWhile place expressions like `bits[index] = value;` are not available, `bitvec`\ninstead provides a proxy structure that can be used as *nearly* an `\u0026mut bit`\nreference:\n\n```rust\nuse bitvec::prelude::*;\n\nlet bits = bits![mut 0];\n// `bit` is not a reference, so\n// it must be bound with `mut`.\nlet mut bit = bits.get_mut(0).unwrap();\nassert!(!*bit);\n*bit = true;\nassert!(*bit);\n// `bit` is not a reference,\n// so NLL rules do not apply.\ndrop(bit);\nassert!(bits[0]);\n```\n\nThe `bitvec` data types implement a complete replacement for their\nstandard-library counterparts, including all of the inherent methods, traits,\nand operator behaviors.\n\n## User Stories\n\nUses of `bitvec` generally fall into three major genres.\n\n- compact, fast, `usize =\u003e bit` collections\n- truncated integer storage\n- precise control of memory layout\n\n### Bit Collections\n\nAt its most basic, `bitvec` provides sequence types analogous to the standard\nlibrary’s `bool` collections. The default behavior is optimized for fast memory\naccess and simple codegen, and can compact `[bool]` or `Vec\u003cbool\u003e` with minimal\noverhead.\n\nWhile `bitvec` does not attempt to take advantage of SIMD or other vectorized\ninstructions in its default work, its codegen should be a good candidate for\nautovectorization in LLVM. If explicit vectorization is important to you, please\n[file an issue][issue].\n\nExample uses might be implementing a Sieve of Eratosthenes to store primes, or\nother collections that test a yes/no property of a number; or replacing\n`Vec\u003cOption\u003cT\u003e\u003e` with `(BitVec, Vec\u003cMaybeUninit\u003cT\u003e\u003e`).\n\nTo get started, you can perform basic text replacement on your project.\nTranslate any existing types as follows:\n\n- `[bool; N]` becomes `BitArray`\n- `[bool]` becomes `BitSlice`\n- `Vec\u003cbool\u003e` becomes `BitVec`\n- `Box\u003c[bool]\u003e` becomes `BitBox`\n\nand then follow any compiler errors that arise.\n\n### Bit-Field Memory Access\n\nA single bit of information has very few uses. `bitvec` also enables you to\nstore integers wider than a single bit, by selecting a bit-slice and using the\n[`BitField`] trait on it. You can store and retrieve both unsigned and signed\nintegers, as long as the ordering type parameter is [`Lsb0`] or [`Msb0`].\n\nIf your bit-field storage buffers are never serialized for exchange between\nmachines, then you can get away with using the default type parameters and\nunadorned load/store methods. While the in-memory layout of stored integers may\nbe surprising if directly inspected, the overall behavior should be optimal for\nyour target.\n\nRemember: `bitvec` only provides array place expressions, using integer start\nand end points. You can use [`deku`] if you want C-style named structural fields\nwith bit-field memory storage.\n\nHowever, if you are de/serializing buffers for transport, then you fall into the\nthird category.\n\n### Transport Protocols\n\nMany protocols use sub-element fields in order to save space in transport; for\nexample, TCP headers have single-bit and 4-bit fields in order to pack all the\nneeded information into a desirable amount of space. In C or Erlang, these TCP\nprotocol fields could be mapped by record fields in the language. In Rust, they\ncan be mapped by indexing into a bit-slice.\n\nWhen using `bitvec` to manage protocol buffers, you will need to select the\nexact type parameters that match your memory layout. For instance, TCP uses\n`\u003cu8, Msb0\u003e`, while IPv6 on a little-endian machine uses `\u003cu32, Lsb0\u003e`. Once you\nhave done this, you can replace all of your `(memory \u0026 mask) \u003e\u003e shift` or\n`memory |= (value \u0026 mask) \u003c\u003c shift` expressions with `memory[start .. end]`.\n\nAs a direct example, the Itanium instruction set IA-64 uses very-long\ninstruction words containing three 41-bit fields in a `[u8; 16]`. One IA-64\ndisassembler replaced its manual shift/mask implementation with `bitvec` range\nindexing, taking the bit numbers directly from the datasheet, and observed that\ntheir code was both easier to maintain and also had better performance as a\nresult!\n\n## Feature Flags\n\n`bitvec` has a few Cargo features that govern its API surface. The default\nfeature set is:\n\n```toml\n[dependencies.bitvec]\nversion = \"1\"\nfeatures = [\n  \"alloc\",\n  \"atomic\",\n  # \"serde\",\n  \"std\",\n]\n```\n\nUse `default-features = false` to disable all of them, then `features = []` to\nrestore the ones you need.\n\n- `alloc`: This links against the `alloc` distribution crate, and provides the\n  `BitVec` and `BitBox` types. It can be used on `#![no_std]` targets that\n  possess a dynamic allocator but not an operating system.\n\n- `atomic`: This controls whether atomic instructions can be used for aliased\n  memory. `bitvec` uses the [`radium`] crate to perform automatic detection of\n  atomic capability, and targets that do not possess atomic instructions can\n  still function with this feature *enabled*. Its only effect is that targets\n  which do have atomic instructions may choose to disable it and enforce\n  single-threaded behavior that never incurs atomic synchronization.\n\n- `serde`: This enables the de/serialization of `bitvec` buffers through the\n  `serde` system. This can be useful if you need to transmit `usize =\u003e bool`\n  collections.\n\n- `std`: This provides some `std::io::{Read,Write}` implementations, as well as\n  `std::error::Error` for the various error types. It is otherwise unnecessary.\n\n## Deeper Reading\n\nThe [API Documentation][docsrs] explores `bitvec`’s usage and implementation in\ngreat detail. In particular, you should read the documentation for the\n[`order`], [`store`], and [`field`] modules, as well as the [`BitSlice`] and\n[`BitArray`] types.\n\nIn addition, the [user guide][guide] explores the philosophical and academic\nconcepts behind `bitvec`’s construction, its goals, and the more intricate parts\nof its behavior.\n\nWhile you should be able to get started with `bitvec` with only dropping it into\nyour code and using the same habits you have with the standard library, both of\nthese resources contain all of the information needed to understand what it\ndoes, how it works, and how it can be useful to you.\n\n\u003c!-- Badges --\u003e\n[crate_link]: https://crates.io/crates/bitvec \"Crate listing\"\n[crate_img]: https://img.shields.io/crates/v/bitvec.svg?style=for-the-badge\u0026color=f46623 \"Crate badge\"\n[docs_link]: https://docs.rs/bitvec/latest/bitvec \"Crate documentation\"\n[docs_img]: https://img.shields.io/docsrs/bitvec/latest.svg?style=for-the-badge \"Documentation badge\"\n[downloads_img]: https://img.shields.io/crates/dv/bitvec.svg?style=for-the-badge \"Crate downloads\"\n[license_file]: https://github.com/ferrilab/bitvec/blob/main/LICENSE.txt \"Project license\"\n[license_img]: https://img.shields.io/crates/l/bitvec.svg?style=for-the-badge \"License badge\"\n[msrv_img]: https://img.shields.io/badge/MSRV-1.56-f46623?style=for-the-badge\u0026logo=rust \"Minimum Supported Rust Version: 1.56\"\n\n\u003c!-- Documentation --\u003e\n[`BitArray`]: https://docs.rs/bitvec/latest/bitvec/array/struct.BitArray.html\n[`BitField`]: https://docs.rs/bitvec/latest/bitvec/field/trait.BitField.html\n[`BitSlice`]: https://docs.rs/bitvec/latest/bitvec/slice/struct.BitSlice.html\n[`Lsb0`]: https://docs.rs/bitvec/latest/bitvec/order/struct.Lsb0.html\n[`Msb0`]: https://docs.rs/bitvec/latest/bitvec/order/struct.Msb0.html\n[`field`]: https://docs.rs/bitvec/latest/bitvec/field/index.html\n[`order`]: https://docs.rs/bitvec/latest/bitvec/order/index.html\n[`store`]: https://docs.rs/bitvec/latest/bitvec/store/index.html\n[prelude]: https://docs.rs/bitvec/latest/bitvec/prelude\n\n\u003c!-- External References --\u003e\n[`deku`]: https://crates.io/crates/deku\n[docsrs]: https://docs.rs/bitvec/latest/bitvec\n[erl_bit]: https://www.erlang.org/doc/programming_examples/bit_syntax.html\n[guide]: https://ferrilab.github.io/bitvec/\n[issue]: https://github.com/ferrilab/bitvec/issues/new\n[moz]: https://hacks.mozilla.org/2021/04/eliminating-data-races-in-firefox-a-technical-report/ \"Mozilla Hacks article describing various concurrency bugs in FireFox\"\n[`radium`]: https://crates.io/crates/radium\n[`std::bitset\u003cN\u003e`]: https://en.cppreference.com/w/cpp/utility/bitset\n[`std::vector\u003cbool\u003e`]: https://en.cppreference.com/w/cpp/container/vector_bool\n","funding_links":[],"categories":["Rust"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fferrilab%2Fbitvec","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fferrilab%2Fbitvec","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fferrilab%2Fbitvec/lists"}