{"id":22919285,"url":"https://github.com/robbepop/modular-bitfield","last_synced_at":"2025-04-13T09:58:45.482Z","repository":{"id":34898874,"uuid":"188103947","full_name":"Robbepop/modular-bitfield","owner":"Robbepop","description":"Macro to generate bitfields for structs that allow for modular use of enums.","archived":false,"fork":false,"pushed_at":"2025-03-31T09:59:42.000Z","size":543,"stargazers_count":184,"open_issues_count":30,"forks_count":44,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-06T06:01:49.763Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Robbepop.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-05-22T19:49:54.000Z","updated_at":"2025-04-02T07:02:52.000Z","dependencies_parsed_at":"2024-06-18T20:00:06.932Z","dependency_job_id":"d865d73c-2c06-4582-bd9e-81ee346fed0f","html_url":"https://github.com/Robbepop/modular-bitfield","commit_stats":{"total_commits":219,"total_committers":9,"mean_commits":"24.333333333333332","dds":"0.10502283105022836","last_synced_commit":"b24388c40b58c18c4fdf8f9cd561bf0e75b86ae2"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Robbepop%2Fmodular-bitfield","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Robbepop%2Fmodular-bitfield/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Robbepop%2Fmodular-bitfield/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Robbepop%2Fmodular-bitfield/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Robbepop","download_url":"https://codeload.github.com/Robbepop/modular-bitfield/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248695319,"owners_count":21146952,"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":[],"created_at":"2024-12-14T07:07:17.982Z","updated_at":"2025-04-13T09:58:45.454Z","avatar_url":"https://github.com/Robbepop.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Modular Bitfields for Rust\n\n|   Continuous Integration  |  Documentation    |       Crates.io      |       LoC        |\n|:-------------------------:|:-----------------:|:--------------------:|:----------------:|\n| [![GHActions][C1]][C2]    | [![docs][A1]][A2] | [![crates][B1]][B2]  | [![loc][D1]][D2] |\n\n[A1]: https://docs.rs/modular-bitfield/badge.svg\n[A2]: https://docs.rs/modular-bitfield\n[B1]: https://img.shields.io/crates/v/modular_bitfield.svg\n[B2]: https://crates.io/crates/modular_bitfield\n[C1]: https://github.com/Robbepop/modular-bitfield/workflows/Rust%20-%20Continuous%20Integration/badge.svg?branch=master\u0026event=push\n[C2]: https://github.com/Robbepop/modular-bitfield/actions?query=workflow%3A%22Rust+-+Continuous+Integration%22+branch%3Amaster+event%3Apush\n[D1]: https://tokei.rs/b1/github/Robbepop/modular-bitfield?category=code\n[D2]: https://github.com/Aaronepower/tokei#badges\n\n- `no_std`: Supports embedded development without `std` library.\n- This crate uses and generates 100% safe Rust code.\n\n## Description\n\nAllows to have bitfield structs and enums as bitfield specifiers that work very similar to C and C++ bitfields.\n\n## Advantages\n\n- **Safety:** Macro embraced enums and structs are checked for valid structure during compilation time.\n- **Speed:** Generated code is as fast as handwritten code. (See benchmarks below.)\n- **Modularity:** Enums can be used modular within bitfield structs.\n\n## Attribution\n\nImplements the `#[bitfield]` macros introduced and specified in David Tolnay's [procedural macro workshop][procedural-macro-workshop].\n\nThanks go to David Tolnay for designing the specification for the macros implemented in this crate.\n\n## Usage\n\nAnnotate a Rust struct with the `#[bitfield]` attribute in order to convert it into a bitfield.\nThe `B1`, `B2`, ... `B128` prelude types can be used as primitives to declare the number of bits per field.\n\n```rust\n#[bitfield]\npub struct PackedData {\n    header: B4,\n    body: B9,\n    is_alive: B1,\n    status: B2,\n}\n ```\n\nThis produces a `new` constructor as well as a variety of getters and setters that\nallows to interact with the bitfield in a safe fashion:\n\n### Example: Constructors\n\n```rust\nlet data = PackedData::new()\n    .with_header(1)\n    .with_body(2)\n    .with_is_alive(0)\n    .with_status(3);\nassert_eq!(data.header(), 1);\nassert_eq!(data.body(), 2);\nassert_eq!(data.is_alive(), 0);\nassert_eq!(data.status(), 3);\n```\n\n### Example: Primitive Types\n\nAny type that implements the `Specifier` trait can be used as a bitfield field.\nBesides the already mentioned `B1`, .. `B128` also the `bool`, `u8`, `u16`, `u32`,\n`u64` or `u128` primitive types can be used from prelude.\n\nWe can use this knowledge to encode our `is_alive` as `bool` type instead of `B1`:\n\n```rust\n#[bitfield]\npub struct PackedData {\n    header: B4,\n    body: B9,\n    is_alive: bool,\n    status: B2,\n}\n\nlet mut data = PackedData::new()\n    .with_is_alive(true);\nassert!(data.is_alive());\ndata.set_is_alive(false);\nassert!(!data.is_alive());\n```\n\n### Example: Enum Specifiers\n\nIt is possible to derive the `Specifier` trait for `enum` types very easily to make\nthem also usable as a field within a bitfield type:\n\n```rust\n#[derive(BitfieldSpecifier)]\npub enum Status {\n    Red, Green, Yellow, None,\n}\n\n#[bitfield]\npub struct PackedData {\n    header: B4,\n    body: B9,\n    is_alive: bool,\n    status: Status,\n}\n```\n\n### Example: Extra Safety Guard\n\nIn order to make sure that our `Status` enum still requires exatly 2 bit we can add\n`#[bits = 2]` to its field:\n\n```rust\n#[bitfield]\npub struct PackedData {\n    header: B4,\n    body: B9,\n    is_alive: bool,\n    #[bits = 2]\n    status: Status,\n}\n```\n\nSetting and getting our new `status` field is naturally as follows:\n\n```rust\nlet mut data = PackedData::new()\n    .with_status(Status::Green);\nassert_eq!(data.status(), Status::Green);\ndata.set_status(Status::Red);\nassert_eq!(data.status(), Status::Red);\n```\n\n### Example: Recursive Bitfields\n\nIt is possible to use `#[bitfield]` structs as fields of `#[bitfield]` structs.\nThis is generally useful if there are some common fields for multiple bitfields\nand is achieved by adding `#[derive(BitfieldSpecifier)]` to the attributes of the\n`#[bitfield]` annotated struct:\n\n```rust\n#[bitfield]\n#[derive(BitfieldSpecifier)]\npub struct Header {\n    is_compact: bool,\n    is_secure: bool,\n    pre_status: Status,\n}\n\n#[bitfield]\npub struct PackedData {\n    header: Header,\n    body: B9,\n    is_alive: bool,\n    status: Status,\n}\n```\n\nWith the `bits: int` parameter of the `#[bitfield]` macro on the `Header` struct and the\n`#[bits: int]` attribute of the `#[derive(BitfieldSpecifier)]` on the `Status` enum we\ncan have additional compile-time guarantees about the bit widths of the resulting entities:\n\n```rust\n#[derive(BitfieldSpecifier)]\n#[bits = 2]\npub enum Status {\n    Red, Green, Yellow\n}\n\n#[bitfield(bits = 4)]\n#[derive(BitfieldSpecifier)]\npub struct Header {\n    is_compact: bool,\n    is_secure: bool,\n    #[bits = 2]\n    pre_status: Status,\n}\n\n#[bitfield(bits = 16)]\npub struct PackedData {\n    #[bits = 4]\n    header: Header,\n    body: B9,\n    is_alive: bool,\n    #[bits = 2]\n    status: Status,\n}\n```\n\n### Example: Advanced Enum Specifiers\n\nFor our `Status` enum we actually just need 3 status variants: `Green`, `Yellow` and `Red`.\nWe introduced the `None` status variants because `Specifier` enums by default are required\nto have a number of variants that is a power of two. We can ship around this by specifying\n`#[bits = 2]` on the top and get rid of our placeholder `None` variant while maintaining\nthe invariant of it requiring 2 bits:\n\n```rust\n# use modular_bitfield::prelude::*;\n\n#[derive(BitfieldSpecifier)]\n#[bits = 2]\npub enum Status {\n    Red, Green, Yellow,\n}\n```\n\nHowever, having such enums now yields the possibility that a bitfield might contain invalid bit\npatterns for such fields. We can safely access those fields with protected getters. For the sake\nof demonstration we will use the generated `from_bytes` constructor with which we can easily\nconstruct bitfields that may contain invalid bit patterns:\n\n```rust\nlet mut data = PackedData::from_bytes([0b0000_0000, 0b1100_0000]);\n//           The 2 status field bits are invalid -----^^\n//           as Red = 0x00, Green = 0x01 and Yellow = 0x10\nassert_eq!(data.status_or_err(), Err(InvalidBitPattern { invalid_bytes: 0b11 }));\ndata.set_status(Status::Green);\nassert_eq!(data.status_or_err(), Ok(Status::Green));\n```\n\n## Benchmarks\n\nBelow are some benchmarks between the [hand-written code][benchmark-code] and the macro-generated code for some example getters and setters that cover a decent variety of use cases.\n\nWe can conclude that the macro-generated code is as fast as hand-written code would be. Please file a PR if you see a way to improve either side.\n\n- `cargo bench` to run the benchmarks\n- `cargo test --benches` to run the benchmark tests\n\n[Click here to view all benchmark results.][benchmark-results]\n\n[benchmark-code]: https://github.com/Robbepop/modular-bitfield/blob/master/benches/handwritten.rs\n[benchmark-results]: https://gist.github.com/Robbepop/bcff4fe149e0e622b752f0eb07b31880\n\n### Summary\n\nThe `modular_bitfield` crate generates bitfields that are ...\n\n- just as efficient as the handwritten alternatives.\n- equally efficient or more efficient than the alternative [bitfield] crate.\n\n[bitfield]: https://crates.io/crates/bitfield\n\n### Showcase: Generated vs Handwritten\n\nWe tested the following `#[bitfield]` `struct`:\n\n```rust\n#[bitfield]\npub struct Generated {\n    pub a: B9,  // Spans 2 bytes.\n    pub b: B6,  // Within 2nd byte.\n    pub c: B13, // Spans 3 bytes.\n    pub d: B1,  // Within 4rd byte.\n    pub e: B3,  // Within 4rd byte.\n    pub f: B32, // Spans rest 4 bytes.\n}\n```\n\n**Note:** All benchmarks timing results sum 10 runs each.\n\n### Getter Performance\n\n```\nget_a/generated     time:   [3.0990 ns 3.1119 ns 3.1263 ns]\nget_a/handwritten   time:   [3.1072 ns 3.1189 ns 3.1318 ns]\n\nget_b/generated     time:   [3.0859 ns 3.0993 ns 3.1140 ns]\nget_b/handwritten   time:   [3.1062 ns 3.1154 ns 3.1244 ns]\n\nget_c/generated     time:   [3.0892 ns 3.1140 ns 3.1491 ns]\nget_c/handwritten   time:   [3.1031 ns 3.1144 ns 3.1266 ns]\n\nget_d/generated     time:   [3.0937 ns 3.1055 ns 3.1182 ns]\nget_d/handwritten   time:   [3.1109 ns 3.1258 ns 3.1422 ns]\n\nget_e/generated     time:   [3.1009 ns 3.1139 ns 3.1293 ns]\nget_e/handwritten   time:   [3.1217 ns 3.1366 ns 3.1534 ns]\n\nget_f/generated     time:   [3.1064 ns 3.1164 ns 3.1269 ns]\nget_f/handwritten   time:   [3.1067 ns 3.1221 ns 3.1404 ns]\n```\n\n### Setter Performance\n\n```\nset_a/generated     time:   [15.784 ns 15.855 ns 15.932 ns]\nset_a/handwritten   time:   [15.841 ns 15.907 ns 15.980 ns]\n\nset_b/generated     time:   [20.496 ns 20.567 ns 20.643 ns]\nset_b/handwritten   time:   [20.319 ns 20.384 ns 20.454 ns]\n\nset_c/generated     time:   [19.155 ns 19.362 ns 19.592 ns]\nset_c/handwritten   time:   [19.265 ns 19.383 ns 19.523 ns]\n\nset_d/generated     time:   [12.325 ns 12.376 ns 12.429 ns]\nset_d/handwritten   time:   [12.416 ns 12.472 ns 12.541 ns]\n\nset_e/generated     time:   [20.460 ns 20.528 ns 20.601 ns]\nset_e/handwritten   time:   [20.473 ns 20.534 ns 20.601 ns]\n\nset_f/generated     time:   [6.1466 ns 6.1769 ns 6.2127 ns]\nset_f/handwritten   time:   [6.1467 ns 6.1962 ns 6.2670 ns]\n```\n\n## License\n\nLicensed under either of \u003ca href=\"LICENSE-APACHE\"\u003eApache License, Version\n2.0\u003c/a\u003e or \u003ca href=\"LICENSE-MIT\"\u003eMIT license\u003c/a\u003e at your option.\n\nUnless you explicitly state otherwise, any contribution intentionally submitted\nfor inclusion in this codebase by you, as defined in the Apache-2.0 license,\nshall be dual licensed as above, without any additional terms or conditions.\n\n[procedural-macro-workshop]: https://github.com/dtolnay/proc-macro-workshop/blob/master/README.md\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobbepop%2Fmodular-bitfield","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobbepop%2Fmodular-bitfield","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobbepop%2Fmodular-bitfield/lists"}