{"id":21828054,"url":"https://github.com/wrenger/bitfield-struct-rs","last_synced_at":"2025-05-15T15:02:39.611Z","repository":{"id":62438014,"uuid":"440571940","full_name":"wrenger/bitfield-struct-rs","owner":"wrenger","description":"Procedural macro for bitfields.","archived":false,"fork":false,"pushed_at":"2025-01-26T11:21:53.000Z","size":114,"stargazers_count":86,"open_issues_count":6,"forks_count":20,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-31T22:14:31.867Z","etag":null,"topics":["bitfield","embedded","no-std","os","rust"],"latest_commit_sha":null,"homepage":"","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/wrenger.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2021-12-21T15:55:58.000Z","updated_at":"2025-03-29T08:22:29.000Z","dependencies_parsed_at":"2023-12-16T11:41:41.040Z","dependency_job_id":"9dd54026-e88f-4f30-b4d9-7f44721a4191","html_url":"https://github.com/wrenger/bitfield-struct-rs","commit_stats":{"total_commits":33,"total_committers":2,"mean_commits":16.5,"dds":"0.18181818181818177","last_synced_commit":"ff0107b1c237348ca266d9a1fe2d041dde093f75"},"previous_names":[],"tags_count":31,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wrenger%2Fbitfield-struct-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wrenger%2Fbitfield-struct-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wrenger%2Fbitfield-struct-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wrenger%2Fbitfield-struct-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wrenger","download_url":"https://codeload.github.com/wrenger/bitfield-struct-rs/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247744291,"owners_count":20988781,"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":["bitfield","embedded","no-std","os","rust"],"created_at":"2024-11-27T18:15:00.974Z","updated_at":"2025-05-15T15:02:39.592Z","avatar_url":"https://github.com/wrenger.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"# Bitfield Struct\n\n[![Crate](https://img.shields.io/crates/v/bitfield-struct.svg)](https://crates.io/crates/bitfield-struct)\n[![API](https://docs.rs/bitfield-struct/badge.svg)](https://docs.rs/bitfield-struct)\n\nProcedural macro for bitfields that allows specifying bitfields as structs.\nAs this library provides a procedural macro, it has no runtime dependencies and works for `no-std` environments.\n\n- Ideal for driver/OS/embedded development (defining HW registers/structures)\n- Supports bool flags, integers, and custom types convertible into integers (structs/enums)\n- Generates minimalistic, pure, safe rust functions\n- Compile-time checks for type and field sizes\n- Rust-analyzer/docrs friendly (carries over docs to accessor functions)\n- Exports field offsets and sizes as constants (useful for const asserts)\n- Optional generation of `Default`, `Clone`, `Debug`, `Hash`, or `defmt::Format` traits\n- Custom internal representation (endianness)\n\n## Usage\n\nAdd this to your `Cargo.toml`:\n\n```toml\n[dependencies]\nbitfield-struct = \"0.11\"\n```\n\n## Basics\n\nLet's begin with a simple example.\nSuppose we want to store multiple data inside a single Byte, as shown below:\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e7\u003c/td\u003e\n    \u003ctd\u003e6\u003c/td\u003e\n    \u003ctd\u003e5\u003c/td\u003e\n    \u003ctd\u003e4\u003c/td\u003e\n    \u003ctd\u003e3\u003c/td\u003e\n    \u003ctd\u003e2\u003c/td\u003e\n    \u003ctd\u003e1\u003c/td\u003e\n    \u003ctd\u003e0\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eP\u003c/td\u003e\n    \u003ctd colspan=\"2\"\u003eLevel\u003c/td\u003e\n    \u003ctd\u003eS\u003c/td\u003e\n    \u003ctd colspan=\"4\"\u003eKind\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nThis crate generates a nice wrapper type that makes it easy to do this:\n\n```rust\nuse bitfield_struct::bitfield;\n\n/// Define your type like this with the bitfield attribute\n#[bitfield(u8)]\nstruct MyByte {\n    /// The first field occupies the least significant bits\n    #[bits(4)]\n    kind: usize,\n    /// Booleans are 1 bit large\n    system: bool,\n    /// The bits attribute specifies the bit size of this field\n    #[bits(2)]\n    level: usize,\n    /// The last field spans over the most significant bits\n    present: bool\n}\n// The macro creates three accessor functions for each field:\n// \u003cname\u003e, with_\u003cname\u003e and set_\u003cname\u003e\nlet my_byte = MyByte::new()\n    .with_kind(15)\n    .with_system(false)\n    .with_level(3)\n    .with_present(true);\n\nassert!(my_byte.present());\n```\n\n## Features\n\nAdditionally, this crate has a few useful features, which are shown here in more detail.\n\nThe example below shows how attributes are carried over and how signed integers, padding, and custom types are handled.\n\n```rust\nuse bitfield_struct::bitfield;\n\n/// A test bitfield with documentation\n#[bitfield(u64)]\n#[derive(PartialEq, Eq)] // \u003c- Attributes after `bitfield` are carried over\nstruct MyBitfield {\n    /// Defaults to 16 bits for u16\n    int: u16,\n    /// Interpreted as 1 bit flag, with a custom default value\n    #[bits(default = true)]\n    flag: bool,\n    /// Custom bit size\n    #[bits(1)]\n    tiny: u8,\n    /// Sign extend for signed integers\n    #[bits(13)]\n    negative: i16,\n    /// Supports any type with `into_bits`/`from_bits` functions\n    #[bits(16)]\n    custom: CustomEnum,\n    /// Public field -\u003e public accessor functions\n    #[bits(10)]\n    pub public: usize,\n    /// Also supports read-only fields\n    #[bits(1, access = RO)]\n    read_only: bool,\n    /// And write-only fields\n    #[bits(1, access = WO)]\n    write_only: bool,\n    /// Padding\n    #[bits(5)]\n    __: u8,\n}\n\n/// A custom enum\n#[derive(Debug, PartialEq, Eq)]\n#[repr(u16)]\nenum CustomEnum {\n    A = 0,\n    B = 1,\n    C = 2,\n}\nimpl CustomEnum {\n    // This has to be a const fn\n    const fn into_bits(self) -\u003e u16 {\n        self as _\n    }\n    const fn from_bits(value: u16) -\u003e Self {\n        match value {\n            0 =\u003e Self::A,\n            1 =\u003e Self::B,\n            _ =\u003e Self::C,\n        }\n    }\n}\n\n// Usage:\nlet mut val = MyBitfield::new()\n    .with_int(3 \u003c\u003c 15)\n    .with_tiny(1)\n    .with_negative(-3)\n    .with_custom(CustomEnum::B)\n    .with_public(2)\n    // .with_read_only(true) \u003c- Would not compile\n    .with_write_only(false);\n\nprintln!(\"{val:?}\");\nlet raw: u64 = val.into();\nprintln!(\"{raw:b}\");\n\nassert_eq!(val.int(), 3 \u003c\u003c 15);\nassert_eq!(val.flag(), true);\nassert_eq!(val.negative(), -3);\nassert_eq!(val.tiny(), 1);\nassert_eq!(val.custom(), CustomEnum::B);\nassert_eq!(val.public(), 2);\nassert_eq!(val.read_only(), false);\n\n// const members\nassert_eq!(MyBitfield::FLAG_BITS, 1);\nassert_eq!(MyBitfield::FLAG_OFFSET, 16);\n\nval.set_negative(1);\nassert_eq!(val.negative(), 1);\n```\n\nThe macro generates three accessor functions for each field.\nEach accessor also inherits the documentation of its field.\n\nThe signatures for `int` are:\n\n```rust\n// generated struct\nstruct MyBitfield(u64);\nimpl MyBitfield {\n    const fn new() -\u003e Self { Self(0) }\n\n    const INT_BITS: usize = 16;\n    const INT_OFFSET: usize = 0;\n\n    const fn int(\u0026self) -\u003e u16 { todo!() }\n\n    const fn with_int(self, value: u16) -\u003e Self { todo!() }\n    const fn with_int_checked(self, value: u16) -\u003e Result\u003cSelf, ()\u003e { todo!() }\n\n    const fn set_int(\u0026mut self, value: u16) { todo!() }\n    const fn set_int_checked(\u0026mut self, value: u16) -\u003e Result\u003c(), ()\u003e { todo!() }\n\n    // other field ...\n}\n// Also generates From\u003cu64\u003e, Into\u003cu64\u003e, Default, and Debug implementations...\n```\n\n\u003e Hint: You can use the rust-analyzer \"Expand macro recursively\" action to view the generated code.\n\n## Custom Types\n\nThe macro supports any types that are convertible into the underlying bitfield type.\nThis can be enums like in the following example or any other struct.\n\nThe conversion and default values can be specified with the following `#[bits]` parameters:\n- `from`: Function converting from raw bits into the custom type, defaults to `\u003cty\u003e::from_bits`\n- `into`: Function converting from the custom type into raw bits, defaults to `\u003cty\u003e::into_bits`\n- `default`: Custom expression, defaults to calling `\u003cty\u003e::from_bits(0)`\n\n\n```rust\nuse bitfield_struct::bitfield;\n\n#[bitfield(u16)]\n#[derive(PartialEq, Eq)]\nstruct Bits {\n    /// Supports any convertible type\n    #[bits(8, default = CustomEnum::B, from = CustomEnum::my_from_bits)]\n    custom: CustomEnum,\n    /// And nested bitfields\n    #[bits(8)]\n    nested: Nested,\n}\n\n#[derive(Debug, PartialEq, Eq)]\n#[repr(u8)]\nenum CustomEnum {\n    A = 0,\n    B = 1,\n    C = 2,\n}\nimpl CustomEnum {\n    // This has to be a const fn\n    const fn into_bits(self) -\u003e u8 {\n        self as _\n    }\n    const fn my_from_bits(value: u8) -\u003e Self {\n        match value {\n            0 =\u003e Self::A,\n            1 =\u003e Self::B,\n            _ =\u003e Self::C,\n        }\n    }\n}\n\n/// Bitfields implement the conversion functions automatically\n#[bitfield(u8)]\nstruct Nested {\n    #[bits(4)]\n    lo: u8,\n    #[bits(4)]\n    hi: u8,\n}\n```\n\n## Field Order\n\nThe optional `order` macro argument determines the layout of the bits, with the default being\nLsb (least significant bit) first:\n\n```rust\nuse bitfield_struct::bitfield;\n\n#[bitfield(u8, order = Lsb)]\nstruct MyLsbByte {\n    /// The first field occupies the *least* significant bits\n    #[bits(4)]\n    kind: usize,\n    system: bool,\n    #[bits(2)]\n    level: usize,\n    present: bool\n}\nlet my_byte_lsb = MyLsbByte::new()\n    .with_kind(10)\n    .with_system(false)\n    .with_level(2)\n    .with_present(true);\n\n//                          .- present\n//                          | .- level\n//                          | |  .- system\n//                          | |  | .- kind\nassert_eq!(my_byte_lsb.0, 0b1_10_0_1010);\n```\n\nThe macro generates the reverse order when Msb (most significant bit) is specified:\n\n```rust\nuse bitfield_struct::bitfield;\n\n#[bitfield(u8, order = Msb)]\nstruct MyMsbByte {\n    /// The first field occupies the *most* significant bits\n    #[bits(4)]\n    kind: usize,\n    system: bool,\n    #[bits(2)]\n    level: usize,\n    present: bool\n}\nlet my_byte_msb = MyMsbByte::new()\n    .with_kind(10)\n    .with_system(false)\n    .with_level(2)\n    .with_present(true);\n\n//                          .- kind\n//                          |    .- system\n//                          |    | .- level\n//                          |    | |  .- present\nassert_eq!(my_byte_msb.0, 0b1010_0_10_1);\n```\n\n## Custom Representation and Endianness\n\nThe macro supports custom types for the representation of the bitfield struct.\nThis can be an endian-defining type like in the following examples (from [`endian-num`]) or any other struct that can be converted to and from the main bitfield type.\n\nThe representation and its conversion functions can be specified with the following `#[bitfield]` parameters:\n- `repr` specifies the bitfield's representation in memory\n- `from` to specify a conversion function from repr to the bitfield's integer type\n- `into` to specify a conversion function from the bitfield's integer type to repr\n\n[`endian-num`]: https://docs.rs/endian-num\n\nThis example has a little-endian byte order even on big-endian machines:\n\n```rust\nuse bitfield_struct::bitfield;\nuse endian_num::le16;\n\n#[bitfield(u16, repr = le16, from = le16::from_ne, into = le16::to_ne)]\nstruct MyLeBitfield {\n    #[bits(4)]\n    first_nibble: u8,\n    #[bits(12)]\n    other: u16,\n}\n\nlet my_be_bitfield = MyLeBitfield::new()\n    .with_first_nibble(0x1)\n    .with_other(0x234);\n\nassert_eq!(my_be_bitfield.into_bits().to_le_bytes(), [0x41, 0x23]);\n```\n\nThis example has a big-endian byte order even on little-endian machines:\n\n```rust\nuse bitfield_struct::bitfield;\nuse endian_num::be16;\n\n#[bitfield(u16, repr = be16, from = be16::from_ne, into = be16::to_ne)]\nstruct MyBeBitfield {\n    #[bits(4)]\n    first_nibble: u8,\n    #[bits(12)]\n    other: u16,\n}\n\nlet my_be_bitfield = MyBeBitfield::new()\n    .with_first_nibble(0x1)\n    .with_other(0x234);\n\nassert_eq!(my_be_bitfield.into_bits().to_be_bytes(), [0x23, 0x41]);\n```\n\n## Automatic Trait Implementations\n\n### `Clone`, `Copy`\nBy default, this macro derives `Clone` and `Copy`.\nYou can disable this with the extra `clone` argument if the semantics of cloning your type require it (e.g. the type holds a pointer to owned data that must also be cloned).\nIn this case, you can provide your own implementations for `Clone` and `Copy`.\n\n```rust\nuse bitfield_struct::bitfield;\n\n#[bitfield(u64, clone = false)]\nstruct CustomClone {\n    data: u64\n}\n\nimpl Clone for CustomClone {\n    fn clone(\u0026self) -\u003e Self {\n        Self::new().with_data(self.data())\n    }\n}\n\n// optionally:\nimpl Copy for CustomClone {}\n```\n\n### `fmt::Debug`, `Default`\nBy default, it also generates suitable `fmt::Debug` and `Default` implementations similar to the ones created for normal structs by `#[derive(Debug, Default)]`.\nYou can disable this with the extra `debug` and `default` arguments.\n\n```rust\nuse std::fmt::{Debug, Formatter, Result};\nuse bitfield_struct::bitfield;\n\n#[bitfield(u64, debug = false, default = false)]\nstruct CustomDebug {\n    data: u64\n}\nimpl Debug for CustomDebug {\n    fn fmt(\u0026self, f: \u0026mut Formatter\u003c'_\u003e) -\u003e Result {\n        write!(f, \"0x{:x}\", self.data())\n    }\n}\nimpl Default for CustomDebug {\n    fn default() -\u003e Self {\n        Self(123)\n    }\n}\n\nlet val = CustomDebug::default();\nprintln!(\"{val:?}\")\n```\n\n### Support for `defmt::Format`\n\nThis macro can automatically implement a `defmt::Format` that mirrors the default `fmt::Debug` implementation by passing the extra `defmt` argument.\nThis implementation requires the defmt crate to be available as `defmt`, and has the same rules and caveats as `#[derive(defmt::Format)]`.\n\n```rust\nuse bitfield_struct::bitfield;\n\n#[bitfield(u64, defmt = true)]\nstruct DefmtExample {\n    data: u64\n}\n```\n\n### Support for `std::hash::Hash`\n\nThis macro can also implement `Hash`, which ignores any padding when hashing.\n\n```rust\nuse bitfield_struct::bitfield;\n\n#[bitfield(u64, hash = true)]\nstruct HashExample {\n    __ignored: u32,\n    data: u32,\n}\n```\n\n### Conditionally Enable `new`/`Clone`/`Debug`/`Default`/`defmt::Format`/`Hash`\n\nInstead of booleans, you can specify `cfg(...)` attributes for `new`, `clone`, `debug`, `default`, `defmt` and `hash`:\n\n```rust\nuse bitfield_struct::bitfield;\n\n#[bitfield(u64, debug = cfg(test), default = cfg(feature = \"foo\"))]\nstruct CustomDebug {\n    data: u64\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwrenger%2Fbitfield-struct-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwrenger%2Fbitfield-struct-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwrenger%2Fbitfield-struct-rs/lists"}