├── .gitignore ├── tests ├── compile │ ├── too_big.rs │ ├── too_many.rs │ ├── incorrect_type.rs │ ├── too_big.stderr │ ├── too_many.stderr │ └── incorrect_type.stderr ├── serialization.rs ├── doc_tests.rs └── integration.rs ├── rustfmt.toml ├── Cargo.toml ├── .github └── workflows │ └── ci.yml ├── README.md └── src ├── types.rs └── lib.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | *.profraw 4 | -------------------------------------------------------------------------------- /tests/compile/too_big.rs: -------------------------------------------------------------------------------- 1 | bit_struct::bit_struct! { 2 | struct TooMany(u16) { 3 | a: u32 4 | } 5 | } 6 | 7 | fn main() {} -------------------------------------------------------------------------------- /tests/compile/too_many.rs: -------------------------------------------------------------------------------- 1 | bit_struct::bit_struct! { 2 | struct TooMany(u16) { 3 | a: u8, 4 | b: u8, 5 | c: bit_struct::u1 6 | } 7 | } 8 | 9 | fn main() {} -------------------------------------------------------------------------------- /tests/compile/incorrect_type.rs: -------------------------------------------------------------------------------- 1 | enum EnumNoBits { 2 | A, 3 | B, 4 | } 5 | 6 | bit_struct::bit_struct! { 7 | struct Incorrect(u16) { 8 | a: EnumNoBits 9 | } 10 | } 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | # https://rust-lang.github.io/rustfmt/?version=v1.4.36 2 | unstable_features = true 3 | reorder_imports = true 4 | normalize_comments = true 5 | normalize_doc_attributes = true 6 | imports_granularity = "Crate" 7 | format_macro_matchers = true 8 | format_macro_bodies = true 9 | wrap_comments = true 10 | format_code_in_doc_comments = true 11 | -------------------------------------------------------------------------------- /tests/compile/too_big.stderr: -------------------------------------------------------------------------------- 1 | error[E0080]: evaluation of constant value failed 2 | --> tests/compile/too_big.rs:1:1 3 | | 4 | 1 | / bit_struct::bit_struct! { 5 | 2 | | struct TooMany(u16) { 6 | 3 | | a: u32 7 | 4 | | } 8 | 5 | | } 9 | | |_^ attempt to compute `16_usize - 32_usize`, which would overflow 10 | | 11 | = note: this error originates in the macro `$crate::impl_fields` which comes from the expansion of the macro `bit_struct::bit_struct` (in Nightly builds, run with -Z macro-backtrace for more info) 12 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bit-struct" 3 | version = "0.3.2" 4 | edition = "2021" 5 | description = "Define structs which have fields which are assigned to individual bits, not bytes" 6 | repository = "https://github.com/parallelsystems/bit-struct" 7 | documentation = "https://docs.rs/crate/bit-struct/latest" 8 | readme = "README.md" 9 | license = "MIT OR Apache-2.0" 10 | keywords = ["bit", "struct", "macros"] 11 | categories = ["no-std"] 12 | rust-version = "1.62.1" 13 | 14 | [dependencies] 15 | num-traits = { version = "0.2", default-features = false } 16 | serde = { version = "1.0", default-features = false, features = ["derive"], optional = true } 17 | 18 | [dev-dependencies] 19 | trybuild = "1.0" 20 | matches = "0.1.9" 21 | quickcheck = "1.0" 22 | quickcheck_macros = "1.0" 23 | serde_json = "1.0" 24 | postcard = {version = "1.0.4", features = ["alloc"] } 25 | 26 | [features] 27 | default = ["serde"] 28 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | on: [ push ] 2 | 3 | name: Code Coverage 4 | 5 | jobs: 6 | lint: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | - uses: actions-rs/toolchain@v1 11 | with: 12 | toolchain: nightly 13 | override: true 14 | - uses: actions-rs/cargo@v1 15 | with: 16 | command: test 17 | args: --all-features --no-fail-fast 18 | env: 19 | CARGO_INCREMENTAL: '0' 20 | RUSTFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests' 21 | RUSTDOCFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests' 22 | - id: coverage 23 | uses: actions-rs/grcov@v0.1 24 | - uses: codecov/codecov-action@v2 25 | with: 26 | token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos 27 | files: ${{ steps.coverage.outputs.report }} 28 | fail_ci_if_error: true 29 | -------------------------------------------------------------------------------- /tests/compile/too_many.stderr: -------------------------------------------------------------------------------- 1 | error[E0080]: evaluation of constant value failed 2 | --> tests/compile/too_many.rs:1:1 3 | | 4 | 1 | / bit_struct::bit_struct! { 5 | 2 | | struct TooMany(u16) { 6 | 3 | | a: u8, 7 | 4 | | b: u8, 8 | 5 | | c: bit_struct::u1 9 | 6 | | } 10 | 7 | | } 11 | | |_^ attempt to compute `0_usize - 1_usize`, which would overflow 12 | | 13 | = note: this error originates in the macro `$crate::impl_fields` which comes from the expansion of the macro `bit_struct::bit_struct` (in Nightly builds, run with -Z macro-backtrace for more info) 14 | 15 | error[E0080]: evaluation of constant value failed 16 | --> tests/compile/too_many.rs:1:1 17 | | 18 | 1 | / bit_struct::bit_struct! { 19 | 2 | | struct TooMany(u16) { 20 | 3 | | a: u8, 21 | 4 | | b: u8, 22 | 5 | | c: bit_struct::u1 23 | 6 | | } 24 | 7 | | } 25 | | |_^ attempt to compute `0_usize - 1_usize`, which would overflow 26 | | 27 | = note: this error originates in the macro `$crate::impl_fields` which comes from the expansion of the macro `bit_struct::bit_struct` (in Nightly builds, run with -Z macro-backtrace for more info) 28 | -------------------------------------------------------------------------------- /tests/compile/incorrect_type.stderr: -------------------------------------------------------------------------------- 1 | error[E0277]: the trait bound `EnumNoBits: ValidCheck` is not satisfied 2 | --> tests/compile/incorrect_type.rs:6:1 3 | | 4 | 6 | / bit_struct::bit_struct! { 5 | 7 | | struct Incorrect(u16) { 6 | 8 | | a: EnumNoBits 7 | 9 | | } 8 | 10 | | } 9 | | |_^ the trait `ValidCheck` is not implemented for `EnumNoBits` 10 | | 11 | = help: the following other types implement trait `ValidCheck

`: 12 | bool 13 | i10 14 | i11 15 | i12 16 | i128 17 | i13 18 | i14 19 | i15 20 | and 122 others 21 | = note: this error originates in the macro `bit_struct::bit_struct` (in Nightly builds, run with -Z macro-backtrace for more info) 22 | 23 | error[E0277]: the trait bound `EnumNoBits: BitCount` is not satisfied 24 | --> tests/compile/incorrect_type.rs:6:1 25 | | 26 | 6 | / bit_struct::bit_struct! { 27 | 7 | | struct Incorrect(u16) { 28 | 8 | | a: EnumNoBits 29 | 9 | | } 30 | 10 | | } 31 | | |_^ the trait `BitCount` is not implemented for `EnumNoBits` 32 | | 33 | = help: the following other types implement trait `BitCount`: 34 | bool 35 | i10 36 | i11 37 | i12 38 | i13 39 | i14 40 | i15 41 | i17 42 | and 117 others 43 | = note: this error originates in the macro `$crate::impl_fields` which comes from the expansion of the macro `bit_struct::bit_struct` (in Nightly builds, run with -Z macro-backtrace for more info) 44 | -------------------------------------------------------------------------------- /tests/serialization.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "serde")] 2 | 3 | use quickcheck::{Arbitrary, Gen}; 4 | 5 | bit_struct::enums! { 6 | pub Color { Orange, Red, Blue, Yellow, Green } 7 | } 8 | 9 | bit_struct::bit_struct! { 10 | struct BitStruct(u32) { 11 | a_color: Color, 12 | b: bit_struct::u3, 13 | } 14 | } 15 | 16 | impl Arbitrary for Color { 17 | fn arbitrary(g: &mut Gen) -> Self { 18 | *g.choose(&[ 19 | Self::Orange, 20 | Self::Red, 21 | Self::Blue, 22 | Self::Yellow, 23 | Self::Green, 24 | ]) 25 | .unwrap() 26 | } 27 | } 28 | 29 | impl Arbitrary for BitStruct { 30 | fn arbitrary(g: &mut Gen) -> Self { 31 | let b = *g 32 | .choose(&[ 33 | bit_struct::u3!(0), 34 | bit_struct::u3!(1), 35 | bit_struct::u3!(2), 36 | bit_struct::u3!(3), 37 | bit_struct::u3!(4), 38 | bit_struct::u3!(5), 39 | bit_struct::u3!(6), 40 | bit_struct::u3!(7), 41 | ]) 42 | .unwrap(); 43 | Self::new(Color::arbitrary(g), b) 44 | } 45 | } 46 | 47 | #[quickcheck_macros::quickcheck] 48 | fn test_round_trip_serialize_json_enum(color: Color) -> bool { 49 | use serde_json::{from_value, to_value}; 50 | let round_trip: Color = 51 | from_value(to_value(color).expect("Failed to serialize")).expect("Failed to deserialize"); 52 | round_trip == color 53 | } 54 | 55 | #[quickcheck_macros::quickcheck] 56 | fn test_round_trip_serialize_postcard_enum(color: Color) -> bool { 57 | use postcard::{from_bytes, to_allocvec}; 58 | let round_trip: Color = from_bytes(&to_allocvec(&color).expect("Failed to serialize")) 59 | .expect("Failed to deserialize"); 60 | round_trip == color 61 | } 62 | 63 | #[quickcheck_macros::quickcheck] 64 | fn test_round_trip_serialize_json_struct(bits: BitStruct) -> bool { 65 | use serde_json::{from_value, to_value}; 66 | let round_trip: BitStruct = 67 | from_value(to_value(bits).expect("Failed to serialize")).expect("Failed to deserialize"); 68 | round_trip == bits 69 | } 70 | 71 | #[quickcheck_macros::quickcheck] 72 | fn test_round_trip_serialize_postcard_struct(bits: BitStruct) -> bool { 73 | use postcard::{from_bytes, to_allocvec}; 74 | let round_trip: BitStruct = from_bytes(&to_allocvec(&bits).expect("Failed to serialize")) 75 | .expect("Failed to deserialize"); 76 | round_trip == bits 77 | } 78 | -------------------------------------------------------------------------------- /tests/doc_tests.rs: -------------------------------------------------------------------------------- 1 | bit_struct::enums! { 2 | /// The default value for each enum is always the first 3 | pub ThreeVariants { Zero, One, Two } 4 | 5 | /// This is syntax to set the default value to Cat 6 | pub Animal(Cat) { Cow, Bird, Cat, Dog } 7 | 8 | pub Color { Orange, Red, Blue, Yellow, Green } 9 | } 10 | 11 | bit_struct::bit_struct! { 12 | /// We can write documentation for the struct here. Here BitStruct1 13 | /// derives default values from the above enums macro 14 | struct BitStruct1 (u16){ 15 | /// a 1 bit element. This is stored in u16[15] 16 | a: bit_struct::u1, 17 | 18 | /// This is calculated to take up 2 bits. This is stored in u16[13..=14] 19 | variant: ThreeVariants, 20 | 21 | /// This also takes 2 bits. This is stored in u16[11..=12] 22 | animal: Animal, 23 | 24 | /// This takes up 3 bits. This is stored u16[8..=10] 25 | color: Color, 26 | } 27 | 28 | struct BitStruct2(u32) { 29 | /// We could implement for this too. Note, this does not have a default 30 | a_color: Color, 31 | b: bit_struct::u3, 32 | } 33 | } 34 | 35 | impl Default for BitStruct1 { 36 | fn default() -> Self { 37 | Self::of_defaults() 38 | } 39 | } 40 | 41 | #[test] 42 | fn full_test() { 43 | use std::convert::TryFrom; 44 | 45 | assert_eq!(Animal::default(), Animal::Cat); 46 | assert_eq!(BitStruct1::of_defaults().animal().get(), Animal::Cat); 47 | assert_eq!(BitStruct1::default().animal().get(), Animal::Cat); 48 | 49 | let mut bit_struct: BitStruct1 = BitStruct1::default(); 50 | 51 | assert_eq!(bit_struct.a().start(), 15); 52 | assert_eq!(bit_struct.a().stop(), 15); 53 | 54 | assert_eq!(bit_struct.color().start(), 8); 55 | assert_eq!(bit_struct.color().stop(), 10); 56 | 57 | assert_eq!( 58 | format!("{:?}", bit_struct), 59 | "BitStruct1 { a: 0, variant: Zero, animal: Cat, color: Orange }" 60 | ); 61 | assert_eq!(bit_struct.raw(), 4096); 62 | 63 | let reverse_bit_struct = BitStruct1::try_from(4096); 64 | assert_eq!( 65 | format!("{:?}", reverse_bit_struct), 66 | "Ok(BitStruct1 { a: 0, variant: Zero, animal: Cat, color: Orange })" 67 | ); 68 | 69 | // u3! macro provides a static assert that the number is not too large 70 | let mut other_struct = BitStruct2::new(Color::Green, bit_struct::u3!(0b101)); 71 | assert_eq!( 72 | format!("{:?}", other_struct), 73 | "BitStruct2 { a_color: Green, b: 5 }" 74 | ); 75 | 76 | assert_eq!(other_struct.a_color().get(), Color::Green); 77 | 78 | other_struct.a_color().set(Color::Red); 79 | 80 | assert_eq!(other_struct.a_color().get(), Color::Red); 81 | } 82 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bit-struct 2 | 3 | [![crates.io](https://img.shields.io/crates/v/bit-struct.svg)](https://crates.io/crates/bit-struct) 4 | [![codecov](https://codecov.io/gh/andrewgazelka/bit-struct/branch/main/graph/badge.svg?token=60R82VBBVF)](https://codecov.io/gh/andrewgazelka/bit-struct) 5 | ![Minimum rustc version](https://img.shields.io/badge/rustc-1.62.1+-yellow.svg) 6 | 7 | Bit struct is a crate which allows for ergonomic use of C-like bit fields without mediocre IDE support resulting from proc macros. 8 | In addition, everything is statically typed checked! 9 | 10 | Take the following example 11 | 12 | ```rust 13 | use bit_struct::*; 14 | 15 | enums! { 16 | // 2 bits, i.e., 0b00, 0b01, 0b10 17 | pub HouseKind { Urban, Suburban, Rural} 18 | } 19 | 20 | bit_struct! { 21 | // u8 is the base storage type. This can be any multiple of 8 22 | pub struct HouseConfig(u8) { 23 | // 2 bits 24 | kind: HouseKind, 25 | 26 | // two's compliment 3-bit signed number 27 | lowest_floor: i3, 28 | 29 | // 2 bit unsigned number 30 | highest_floor: u2, 31 | } 32 | } 33 | 34 | // We can create a new `HouseConfig` like such: 35 | // where all numbers are statically checked to be in bounds. 36 | let config = HouseConfig::new(HouseKind::Suburban, i3!(-2), u2!(1)); 37 | 38 | // We can get the raw `u8` which represents `config`: 39 | let raw: u8 = config.raw(); 40 | assert_eq!(114_u8, raw); 41 | 42 | // or we can get a `HouseConfig` from a `u8` like: 43 | let mut config: HouseConfig = HouseConfig::try_from(114_u8).unwrap(); 44 | assert_eq!(config, HouseConfig::new(HouseKind::Suburban, i3!(-2), u2!(1))); 45 | // We need to unwrap because `HouseConfig` is not valid for all numbers. For instance, if the 46 | // most significant bits are `0b11`, it encodes an invalid `HouseKind`. However, 47 | // if all elements of a struct are always valid (suppose we removed the `kind` field), the struct will 48 | // auto implement a trait which allows calling the non-panicking: 49 | // let config: HouseConfig = HouseConfig::exact_from(123_u8); 50 | 51 | // We can access values of `config` like so: 52 | let kind: HouseKind = config.kind().get(); 53 | 54 | // And we can set values like so: 55 | config.lowest_floor().set(i3!(0)); 56 | 57 | // We can also convert the new numeric types for alternate bit-widths into the 58 | // numeric types provided by the standard library: 59 | let lowest_floor: i3 = config.lowest_floor().get(); 60 | let lowest_floor_std: i8 = lowest_floor.value(); 61 | assert_eq!(lowest_floor_std, 0_i8); 62 | ``` 63 | 64 | ## Benefits 65 | - No proc macros 66 | - Autocompletion fully works (tested in IntelliJ Rust) 67 | - Fast compile times 68 | - Statically checks that structs are not overfilled. For example, these overfilled structs will not compile: 69 | ```compile_fail 70 | bit_struct::bit_struct! { 71 | struct TooManyFieldsToFit(u16) { 72 | a: u8, 73 | b: u8, 74 | c: bit_struct::u1 75 | } 76 | } 77 | ``` 78 | ```compile_fail 79 | bit_struct::bit_struct! { 80 | struct FieldIsTooBig(u16) { 81 | a: u32 82 | } 83 | } 84 | ``` 85 | - Statically checked types 86 | 87 | ## Further Documentation 88 | Look at the integration tests in the `tests` folder for further insight. 89 | -------------------------------------------------------------------------------- /tests/integration.rs: -------------------------------------------------------------------------------- 1 | use bit_struct::*; 2 | use num_traits::{Bounded, One, Zero}; 3 | use std::cmp::Ordering; 4 | 5 | #[macro_use] 6 | extern crate matches; 7 | 8 | enums!( 9 | /// A doc comment 10 | pub ModeA(Two) { Zero, One, Two } 11 | pub ModeB(One) { Zero, One, Two } 12 | pub ModeC(Zero) { Zero, One, Two } 13 | ModeD { Zero, One, Two } 14 | OrderA {A, B} 15 | OrderB(B) {A, B} 16 | ); 17 | 18 | bit_struct!( 19 | /// `Abc` struct 20 | struct Abc(u16){ 21 | mode: ModeA, 22 | _padding: u4, 23 | count: u2, 24 | } 25 | 26 | struct FullCount(u16){ 27 | count: u16, 28 | } 29 | 30 | struct NonCoreBase(u24){ 31 | count: u16, 32 | next: u6, 33 | mode: ModeA, 34 | } 35 | 36 | struct Bools(u24){ 37 | flag_a: bool, 38 | flag_b: bool, 39 | } 40 | ); 41 | 42 | impl Default for Abc { 43 | fn default() -> Self { 44 | Self::of_defaults() 45 | } 46 | } 47 | 48 | #[test] 49 | fn test_create() { 50 | let mut abc = create! { 51 | Abc { 52 | mode: ModeA::Two, 53 | count: u2!(2) 54 | } 55 | }; 56 | assert_eq!(abc.mode().get(), ModeA::Two); 57 | assert_eq!(abc.count().get(), u2!(2)); 58 | } 59 | 60 | #[test] 61 | #[allow(clippy::assertions_on_constants)] 62 | fn test_always_valid_enum() { 63 | assert!(!>::ALWAYS_VALID); 64 | assert!(!>::ALWAYS_VALID); 65 | assert!(>::ALWAYS_VALID); 66 | assert!(>::ALWAYS_VALID); 67 | } 68 | 69 | #[test] 70 | fn test_from() { 71 | let mut bools = Bools::exact_from(u24!(0xFF_00_00)); 72 | assert!(bools.flag_a().get()); 73 | assert!(bools.flag_b().get()); 74 | } 75 | 76 | #[test] 77 | fn test_bools() { 78 | let mut bools = Bools::of_defaults(); 79 | assert!(!bools.flag_a().get()); 80 | assert!(!bools.flag_b().get()); 81 | 82 | bools.flag_a().set(true); 83 | assert!(bools.flag_a().get()); 84 | assert!(!bools.flag_b().get()); 85 | 86 | bools.flag_a().set(false); 87 | bools.flag_b().set(true); 88 | assert!(!bools.flag_a().get()); 89 | assert!(bools.flag_b().get()); 90 | 91 | bools.flag_a().set(true); 92 | bools.flag_b().set(true); 93 | assert!(bools.flag_a().get()); 94 | assert!(bools.flag_b().get()); 95 | } 96 | 97 | #[test] 98 | fn test_round_trip_bytes() { 99 | { 100 | let num = u24!(0x04D3); 101 | 102 | let bytes = num.to_be_bytes(); 103 | assert_eq!(bytes, [0x0, 0x4, 0xD3]); 104 | 105 | let num_cloned = u24::from_be_bytes(bytes); 106 | 107 | assert_eq!(num, num_cloned); 108 | } 109 | 110 | { 111 | let num = u24!(1235); 112 | let bytes = num.to_le_bytes(); 113 | let num_cloned = u24::from_le_bytes(bytes); 114 | 115 | assert_eq!(num, num_cloned); 116 | } 117 | 118 | for i in 0..10 { 119 | let res = u24::from(i).value() as u8; 120 | assert_eq!(i, res); 121 | } 122 | } 123 | 124 | #[test] 125 | fn test_invalid() { 126 | assert!(ModeA::is_valid(0_u8)); 127 | assert!(ModeA::is_valid(1_u8)); 128 | assert!(ModeA::is_valid(2_u8)); 129 | assert!(!ModeA::is_valid(3_u8)); 130 | 131 | assert!(ModeD::is_valid(0_u8)); 132 | assert!(ModeD::is_valid(1_u8)); 133 | assert!(ModeD::is_valid(2_u8)); 134 | assert!(!ModeD::is_valid(3_u8)); 135 | } 136 | 137 | #[test] 138 | fn test_non_core_base() { 139 | let mut non_core_base = NonCoreBase::new(123, u6!(13), ModeA::One); 140 | 141 | let count = non_core_base.count().get(); 142 | assert_eq!(count, 123); 143 | 144 | let next = non_core_base.next().get(); 145 | assert_eq!(next.value(), 13); 146 | 147 | let mode = non_core_base.mode().get(); 148 | assert_eq!(mode, ModeA::One); 149 | 150 | let raw = non_core_base.raw(); 151 | 152 | let circle = NonCoreBase::try_from(raw).unwrap(); 153 | assert_eq!(circle, non_core_base); 154 | } 155 | 156 | #[test] 157 | fn test_full_count() { 158 | let full_count = FullCount::new(124); 159 | assert_eq!(full_count.raw(), 124); 160 | } 161 | 162 | #[test] 163 | fn test_of_defaults() { 164 | let full_count = FullCount::of_defaults(); 165 | assert_eq!(full_count.raw(), 0); 166 | } 167 | 168 | #[test] 169 | fn test_toggle() { 170 | let v = u1::TRUE; 171 | assert_eq!(v, u1::TRUE); 172 | assert_eq!(v.toggle(), u1::FALSE); 173 | assert_eq!(v.toggle().toggle(), u1::TRUE); 174 | } 175 | 176 | #[test] 177 | fn test_enum_intos() { 178 | macro_rules! intos { 179 | ($enum_var: ty, $($kind: ty),*) => { 180 | $( 181 | assert_eq!(<$kind>::from(<$enum_var>::Zero), 0); 182 | assert_eq!(<$kind>::from(<$enum_var>::One), 1); 183 | assert_eq!(<$kind>::from(<$enum_var>::Two), 2); 184 | )* 185 | }; 186 | } 187 | 188 | intos!(ModeA, u8, u16, u32, u64, u128); 189 | intos!(ModeD, u8, u16, u32, u64, u128); 190 | } 191 | 192 | #[test] 193 | fn test_ord() { 194 | for a in -0xFF..0xFF { 195 | for b in -0xFF..0xFF { 196 | let a_i9 = i9::new(a).unwrap(); 197 | let b_i9 = i9::new(b).unwrap(); 198 | if a < b { 199 | assert!(a_i9 < b_i9); 200 | assert_eq!(a_i9.cmp(&b_i9), Ordering::Less); 201 | 202 | assert!(b_i9 > a_i9); 203 | assert_eq!(b_i9.cmp(&a_i9), Ordering::Greater); 204 | } 205 | if a > b { 206 | assert!(a_i9 > b_i9); 207 | assert_eq!(a_i9.cmp(&b_i9), Ordering::Greater); 208 | 209 | assert!(b_i9 < a_i9); 210 | assert_eq!(b_i9.cmp(&a_i9), Ordering::Less); 211 | } 212 | if a <= b { 213 | assert!(a_i9 <= b_i9); 214 | assert_matches!(a_i9.cmp(&b_i9), Ordering::Less | Ordering::Equal); 215 | 216 | assert!(b_i9 >= a_i9); 217 | assert_matches!(b_i9.cmp(&a_i9), Ordering::Greater | Ordering::Equal); 218 | } 219 | if a >= b { 220 | assert!(a_i9 >= b_i9); 221 | assert_matches!(a_i9.cmp(&b_i9), Ordering::Greater | Ordering::Equal); 222 | 223 | assert!(b_i9 <= a_i9); 224 | assert_matches!(b_i9.cmp(&a_i9), Ordering::Less | Ordering::Equal); 225 | } 226 | if a == b { 227 | assert_eq!(a_i9, b_i9); 228 | assert_matches!(a_i9.cmp(&b_i9), Ordering::Equal); 229 | 230 | assert_eq!(b_i9, a_i9); 231 | assert_matches!(b_i9.cmp(&a_i9), Ordering::Equal); 232 | } 233 | } 234 | } 235 | } 236 | 237 | #[test] 238 | fn test_enum_defaults() { 239 | // default is manually set to last 240 | assert_eq!(ModeA::default(), ModeA::Two); 241 | assert_eq!(ModeB::default(), ModeB::One); 242 | assert_eq!(ModeC::default(), ModeC::Zero); 243 | assert_eq!(ModeD::default(), ModeD::Zero); 244 | 245 | assert_eq!(OrderA::default(), OrderA::A); 246 | assert_eq!(OrderB::default(), OrderB::B); 247 | } 248 | 249 | #[test] 250 | fn test_bit_struct_defaults() { 251 | let mut abc = Abc::default(); 252 | assert_eq!(abc.count().get(), u2!(0)); 253 | assert_eq!(abc.mode().get(), ModeA::Two); 254 | } 255 | 256 | #[test] 257 | fn test_bit_struct_debug() { 258 | let abc = Abc::default(); 259 | assert_eq!( 260 | format!("{:?}", abc), 261 | "Abc { mode: Two, _padding: 0, count: 0 }" 262 | ); 263 | } 264 | 265 | #[test] 266 | fn test_bit_struct_raw_values() { 267 | let mut abc = Abc::default(); 268 | abc.mode().set(ModeA::One); // 0b01 269 | abc.count().set(u2!(0b10)); 270 | 271 | // 0b 0100 0010 0000 0000 272 | // 0x 4 2 0 0 273 | // 0x4200 274 | assert_eq!(abc.raw(), 0x4200); 275 | 276 | let eq_abc = unsafe { Abc::from_unchecked(0x4200) }; 277 | 278 | assert_eq!(eq_abc.raw(), 0x4200); 279 | assert_eq!(eq_abc, abc); 280 | } 281 | 282 | #[test] 283 | fn test_new_signed_types() { 284 | assert_eq!(i2::MAX, 1); 285 | assert_eq!(i2::max_value(), i2!(1)); 286 | 287 | assert_eq!(i2::MIN, -2); 288 | assert_eq!(i2::min_value(), i2!(-2)); 289 | 290 | assert_eq!(i2!(-2).inner_raw(), 0b10); 291 | assert_eq!(i2!(-1).inner_raw(), 0b11); 292 | assert_eq!(i2!(0).inner_raw(), 0b00); 293 | assert_eq!(i2!(1).inner_raw(), 0b01); 294 | 295 | assert_eq!(i2!(-2).value(), -2); 296 | assert_eq!(i2!(-1).value(), -1); 297 | assert_eq!(i2!(0).value(), 0); 298 | assert_eq!(i2!(1).value(), 1); 299 | 300 | assert_eq!(i3!(-4).inner_raw(), 0b100); 301 | assert_eq!(i3!(-3).inner_raw(), 0b101); 302 | assert_eq!(i3!(-2).inner_raw(), 0b110); 303 | assert_eq!(i3!(-1).inner_raw(), 0b111); 304 | assert_eq!(i3!(0).inner_raw(), 0b000); 305 | assert_eq!(i3!(1).inner_raw(), 0b001); 306 | assert_eq!(i3!(2).inner_raw(), 0b010); 307 | assert_eq!(i3!(3).inner_raw(), 0b011); 308 | 309 | assert_eq!(i3!(-4).inner_raw(), 0b100); 310 | assert_eq!(i3!(-3).inner_raw(), 0b101); 311 | assert_eq!(i3!(-2).inner_raw(), 0b110); 312 | assert_eq!(i3!(-1).inner_raw(), 0b111); 313 | assert_eq!(i3!(0).inner_raw(), 0b000); 314 | assert_eq!(i3!(1).inner_raw(), 0b001); 315 | assert_eq!(i3!(2).inner_raw(), 0b010); 316 | assert_eq!(i3!(3).inner_raw(), 0b011); 317 | 318 | assert!(i3::new(-5).is_none()); 319 | assert!(i3::new(-4).is_some()); 320 | assert!(i3::new(-3).is_some()); 321 | assert!(i3::new(-2).is_some()); 322 | assert!(i3::new(-1).is_some()); 323 | assert!(i3::new(0).is_some()); 324 | assert!(i3::new(1).is_some()); 325 | assert!(i3::new(2).is_some()); 326 | assert!(i3::new(3).is_some()); 327 | assert!(i3::new(4).is_none()); 328 | 329 | assert_eq!(i2::default().value(), 0); 330 | assert_eq!(i3::default().value(), 0); 331 | assert_eq!(i4::default().value(), 0); 332 | } 333 | 334 | fn all_i9s() -> impl Iterator { 335 | (-0xFF..0xFF).filter_map(i9::new) 336 | } 337 | 338 | fn some_i9s() -> impl Iterator { 339 | (-0xD..0xD).filter_map(i9::new) 340 | } 341 | 342 | #[test] 343 | fn test_num_trait() { 344 | macro_rules! eq { 345 | ($a:expr, $b:expr) => { 346 | assert_eq!($a, $b.value()); 347 | }; 348 | } 349 | 350 | macro_rules! eq_assign { 351 | ($operation:ident, $a1:expr, $b1:expr, $a2:expr, $b2:expr) => { 352 | let mut temp1 = $a1; 353 | temp1.$operation($b1); 354 | 355 | let mut temp2 = $a2; 356 | temp2.$operation($b2); 357 | 358 | assert_eq!(temp1, temp2.value()); 359 | }; 360 | } 361 | 362 | assert!(i4::default().is_zero()); 363 | assert!(!i4!(1).is_zero()); 364 | 365 | assert!(i4!(1).is_one()); 366 | assert!(u4!(1).is_one()); 367 | assert!(!i4!(3).is_one()); 368 | assert!(!u4!(0).is_one()); 369 | 370 | assert!(u4::default().is_zero()); 371 | 372 | use core::ops::*; 373 | 374 | for num in some_i9s() { 375 | for shift in 0..=2 { 376 | let actual = num.value(); 377 | eq_assign!(shl_assign, actual, shift, num, shift); 378 | eq_assign!(shr_assign, actual, shift, num, shift); 379 | } 380 | } 381 | 382 | for num in all_i9s() { 383 | let actual = num.value(); 384 | let from = format!("{}", actual); 385 | let a = str::parse::(&from); 386 | let b = str::parse::(&from); 387 | eq!(a.unwrap(), b.unwrap()); 388 | } 389 | 390 | for (a, b) in some_i9s().zip(some_i9s()) { 391 | let actual_a = a.value(); 392 | let actual_b = b.value(); 393 | 394 | eq!(actual_a - actual_b, a - b); 395 | eq!(actual_a + actual_b, a + b); 396 | eq!(actual_a * actual_b, a * b); 397 | 398 | if !b.is_zero() { 399 | eq!(actual_a / actual_b, a / b); 400 | eq!(actual_a % actual_b, a % b); 401 | } 402 | 403 | eq!(actual_a | actual_b, a | b); 404 | eq!(actual_a & actual_b, a & b); 405 | eq!(actual_a ^ actual_b, a ^ b); 406 | eq!(actual_a ^ actual_b, a ^ b); 407 | 408 | eq_assign!(bitand_assign, actual_a, actual_b, a, b); 409 | } 410 | } 411 | 412 | #[test] 413 | fn test_signed_types_formatting() { 414 | for elem in all_i9s() { 415 | let actual = elem.value(); 416 | assert_eq!(format!("{:?}", elem), format!("{:?}", actual)); 417 | assert_eq!(format!("{}", elem), format!("{}", actual)); 418 | } 419 | } 420 | 421 | #[test] 422 | fn test_new_unsigned_types() { 423 | assert_eq!(u1!(0).value(), 0b0); 424 | assert_eq!(u1!(1).value(), 0b1); 425 | 426 | assert_eq!(u1::new(0b0_u8).unwrap().value(), 0); 427 | assert_eq!(u1::new(0b1_u8).unwrap().value(), 1); 428 | assert!(u1::new(0b11_u8).is_none()); 429 | 430 | assert_eq!(u2!(0).value(), 0b00); 431 | assert_eq!(u2!(1).value(), 0b01); 432 | assert_eq!(u2!(2).value(), 0b10); 433 | assert_eq!(u2!(3).value(), 0b11); 434 | assert_eq!(u2::new(0b0_u8).unwrap().value(), 0); 435 | assert_eq!(u2::new(0b1_u8).unwrap().value(), 1); 436 | assert_eq!(u2::new(0b10_u8).unwrap().value(), 2); 437 | assert_eq!(u2::new(0b11_u8).unwrap().value(), 3); 438 | assert!(u2::new(0b100_u8).is_none()); 439 | 440 | assert_eq!(format!("{}", u1!(0)), "0"); 441 | assert_eq!(format!("{}", u1!(1)), "1"); 442 | 443 | assert_eq!(format!("{}", u2!(0)), "0"); 444 | assert_eq!(format!("{}", u2!(1)), "1"); 445 | assert_eq!(format!("{}", u2!(2)), "2"); 446 | assert_eq!(format!("{}", u2!(3)), "3"); 447 | } 448 | 449 | #[test] 450 | fn test_valid_struct() { 451 | // 0b[AA]** **** **** **** 452 | // makes Abc valid where AA is 0b00, 0b01, 0b10 453 | // makes Abc invalid where AA is 0b11 454 | 455 | for first_bits in 0x0..0xF { 456 | let raw = first_bits << 12; 457 | let mode_a_bits = first_bits >> 2; 458 | let conversion = Abc::try_from(raw); 459 | let valid = match mode_a_bits { 460 | 0b00 | 0b01 | 0b10 => conversion.is_ok(), 461 | 0b11 => conversion.is_err(), 462 | _ => panic!("impossible"), 463 | }; 464 | 465 | assert!(valid); 466 | } 467 | } 468 | 469 | #[test] 470 | fn test_bits() { 471 | assert_eq!(bits(0b0), 0); 472 | 473 | assert_eq!(bits(0b1), 1); 474 | 475 | assert_eq!(bits(0b10), 2); 476 | assert_eq!(bits(0b11), 2); 477 | 478 | assert_eq!(bits(0b100), 3); 479 | assert_eq!(bits(0b101), 3); 480 | assert_eq!(bits(0b110), 3); 481 | assert_eq!(bits(0b111), 3); 482 | 483 | assert_eq!(bits(0b1000), 4); 484 | assert_eq!(bits(0b1001), 4); 485 | assert_eq!(bits(0b1010), 4); 486 | assert_eq!(bits(0b1011), 4); 487 | assert_eq!(bits(0b1100), 4); 488 | assert_eq!(bits(0b1101), 4); 489 | assert_eq!(bits(0b1110), 4); 490 | assert_eq!(bits(0b1111), 4); 491 | 492 | assert_eq!(bits(0b10000), 5); 493 | } 494 | 495 | #[test] 496 | fn test_bit_struct_creation() { 497 | let mut abc = Abc::new(ModeA::Two, u4::default(), u2!(0b11)); 498 | assert_eq!(abc.mode().get(), ModeA::Two); 499 | assert_eq!(abc._padding().get(), u4!(0)); 500 | assert_eq!(abc.count().get(), u2!(0b11)); 501 | } 502 | 503 | #[test] 504 | fn fails() { 505 | let t = trybuild::TestCases::new(); 506 | t.compile_fail("tests/compile/*.rs"); 507 | } 508 | -------------------------------------------------------------------------------- /src/types.rs: -------------------------------------------------------------------------------- 1 | //! New integer types used in this crate, and trait implementations for those 2 | //! types 3 | 4 | use super::*; 5 | #[cfg(feature = "serde")] 6 | use serde::{Deserializer, Serializer}; 7 | 8 | /// Assert that the given type is valid for any representation thereof 9 | macro_rules! always_valid { 10 | ($($elem: ty),*) => { 11 | $( 12 | // Safety: 13 | // This is correct: stdlib types are always valid 14 | unsafe impl

ValidCheck

for $elem { 15 | const ALWAYS_VALID: bool = true; 16 | } 17 | )* 18 | }; 19 | } 20 | 21 | /// Implement the [`BitCount`] trait easily for the built-in base types 22 | macro_rules! bit_counts { 23 | ($($num: ty = $count: literal),*) => { 24 | $( 25 | // Safety: 26 | // This is correct for the built-in types 27 | unsafe impl BitCount for $num { 28 | const COUNT: usize = $count; 29 | } 30 | )* 31 | }; 32 | } 33 | 34 | bit_counts!(u8 = 8, u16 = 16, u32 = 32, u64 = 64, u128 = 128, bool = 1); 35 | 36 | /// Implement the [`FieldStorage`] trait for some built-in types 37 | macro_rules! impl_field_storage { 38 | ($(($type:ty, $base:ty)),+ $(,)?) => { 39 | $( 40 | impl FieldStorage for $type { 41 | type StoredType = $base; 42 | 43 | fn inner_raw(self) -> Self::StoredType { 44 | self.into() 45 | } 46 | } 47 | )+ 48 | }; 49 | } 50 | impl_field_storage!( 51 | (bool, u8), 52 | (u8, Self), 53 | (u16, Self), 54 | (u32, Self), 55 | (u64, Self), 56 | (u128, Self), 57 | ); 58 | macro_rules! impl_signed_field_storage { 59 | ($(($type:ty, $base:ty)),+ $(,)?) => { 60 | $( 61 | impl FieldStorage for $type { 62 | type StoredType = $base; 63 | 64 | fn inner_raw(self) -> Self::StoredType { 65 | <$base>::from_le_bytes(self.to_le_bytes()) 66 | } 67 | } 68 | )+ 69 | }; 70 | } 71 | impl_signed_field_storage!((i8, u8), (i16, u16), (i32, u32), (i64, u64), (i128, u128),); 72 | 73 | always_valid!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, bool); 74 | /// Create a type for representing signed integers of sizes not provided by rust 75 | macro_rules! new_signed_types { 76 | ( 77 | $($name: ident($count: literal, $inner: ty, $signed: ty)),* 78 | ) => { 79 | $( 80 | 81 | #[doc = concat!("An unsigned integer which contains ", stringify!($count), " bits")] 82 | #[allow(non_camel_case_types)] 83 | #[derive(Copy, Clone, Eq, PartialEq, Hash)] 84 | pub struct $name($inner); 85 | 86 | always_valid!($name); 87 | 88 | #[cfg(feature = "serde")] 89 | impl serde::Serialize for $name { 90 | fn serialize(&self, serializer: S) -> Result 91 | where 92 | S: Serializer, 93 | { 94 | self.value().serialize(serializer) 95 | } 96 | } 97 | 98 | #[cfg(feature = "serde")] 99 | impl <'de> serde::Deserialize<'de> for $name { 100 | fn deserialize(deserializer: D) -> Result 101 | where 102 | D: Deserializer<'de>, 103 | { 104 | let inner = <$signed>::deserialize(deserializer)?; 105 | $name::new(inner).ok_or(serde::de::Error::custom("invalid size")) 106 | } 107 | } 108 | 109 | impl PartialOrd for $name { 110 | fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> { 111 | self.value().partial_cmp(&other.value()) 112 | } 113 | } 114 | 115 | impl Ord for $name { 116 | fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { 117 | self.value().cmp(&other.value()) 118 | } 119 | } 120 | 121 | impl Debug for $name { 122 | fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { 123 | f.write_fmt(format_args!("{}", self.value())) 124 | } 125 | } 126 | 127 | impl Display for $name { 128 | fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { 129 | f.write_fmt(format_args!("{}", self.value())) 130 | } 131 | } 132 | 133 | #[doc = concat!("Produce a value of type ", stringify!($name))] 134 | /// 135 | /// This macro checks at compile-time that it fits. To check at run-time see the 136 | #[doc = concat!("[`", stringify!($name), "::new`] function.")] 137 | #[macro_export] 138 | macro_rules! $name { 139 | ($value: expr) => { 140 | { 141 | const VALUE: $signed = $value; 142 | const _: () = assert!(VALUE <= $crate::$name::MAX, "The provided value is too large"); 143 | const _: () = assert!(VALUE >= $crate::$name::MIN, "The provided value is too small"); 144 | let res: $name = unsafe {$crate::$name::new_unchecked(VALUE)}; 145 | res 146 | } 147 | }; 148 | } 149 | 150 | // Safety: 151 | // This is guaranteed to be the correct arguments 152 | unsafe impl BitCount for $name { 153 | const COUNT: usize = $count; 154 | } 155 | 156 | num_traits!($name, $signed); 157 | 158 | impl $name { 159 | /// Create a new $name from value 160 | /// # Safety 161 | /// - value must fit within the number of bits defined in the type 162 | pub const unsafe fn new_unchecked(value: $signed) -> Self { 163 | let unsigned_value = value as $inner; 164 | if value >= 0 { 165 | Self(unsigned_value) 166 | } else { 167 | // we can do this 168 | let value = unsigned_value & Self::MAX_UNSIGNED; 169 | Self(value | Self::POLARITY_FLAG) 170 | } 171 | } 172 | 173 | 174 | /// Create a new $name from value 175 | /// # Safety 176 | /// - value must fit within the number of bits defined in the type 177 | pub fn new(value: $signed) -> Option { 178 | if (Self::MIN..=Self::MAX).contains(&value) { 179 | // SAFETY: 180 | // We've just checked that this is safe to call 181 | Some(unsafe {Self::new_unchecked(value)}) 182 | } else { 183 | None 184 | } 185 | } 186 | 187 | const POLARITY_FLAG: $inner = (1 << ($count - 1)); 188 | const MAX_UNSIGNED: $inner = (1 << ($count-1)) - 1; 189 | /// The largest value this type can hold 190 | pub const MAX: $signed = Self::MAX_UNSIGNED as $signed; 191 | /// The smallest value this type can hold 192 | pub const MIN: $signed = -(Self::MAX_UNSIGNED as $signed) - 1; 193 | 194 | /// Get the value stored in here, as a signed integer 195 | pub const fn value(self) -> $signed { 196 | match self.0 >> ($count - 1) { 197 | 0 => self.0 as $signed, 198 | _ => { 199 | // 0's out negative 200 | let rem = self.0 ^ Self::POLARITY_FLAG; 201 | let amount = Self::MAX_UNSIGNED - rem; 202 | -(amount as $signed) - 1 203 | } 204 | } 205 | } 206 | } 207 | 208 | impl Default for $name { 209 | fn default() -> Self { 210 | Self(0) 211 | } 212 | } 213 | 214 | impl FieldStorage for $name { 215 | type StoredType = $inner; 216 | 217 | fn inner_raw(self) -> Self::StoredType { 218 | self.0 219 | } 220 | } 221 | )* 222 | }; 223 | } 224 | 225 | /// Implement traits from the [`num_traits`] crate for our new number types 226 | macro_rules! num_traits { 227 | ($num:ident, $super_kind:ty) => { 228 | impl Zero for $num { 229 | fn zero() -> Self { 230 | $num::new(0).unwrap() 231 | } 232 | 233 | fn is_zero(&self) -> bool { 234 | self.0 == 0 235 | } 236 | } 237 | 238 | impl Add for $num { 239 | type Output = Self; 240 | 241 | fn add(self, rhs: Self) -> Self::Output { 242 | $num::new(self.value() + rhs.value()).unwrap() 243 | } 244 | } 245 | 246 | impl One for $num { 247 | fn one() -> Self { 248 | $num::new(1).unwrap() 249 | } 250 | } 251 | 252 | impl Mul for $num { 253 | type Output = Self; 254 | 255 | fn mul(self, rhs: Self) -> Self::Output { 256 | $num::new(self.value() * rhs.value()).unwrap() 257 | } 258 | } 259 | 260 | impl Sub for $num { 261 | type Output = $num; 262 | 263 | fn sub(self, rhs: Self) -> Self::Output { 264 | $num::new(self.value() - rhs.value()).unwrap() 265 | } 266 | } 267 | 268 | impl Div for $num { 269 | type Output = Self; 270 | 271 | fn div(self, rhs: Self) -> Self::Output { 272 | $num::new(self.value() / rhs.value()).unwrap() 273 | } 274 | } 275 | 276 | impl Rem for $num { 277 | type Output = Self; 278 | 279 | fn rem(self, rhs: Self) -> Self::Output { 280 | $num::new(self.value() % rhs.value()).unwrap() 281 | } 282 | } 283 | 284 | impl Num for $num { 285 | type FromStrRadixErr = (); 286 | 287 | fn from_str_radix(str: &str, radix: u32) -> Result { 288 | let parse = <$super_kind>::from_str_radix(str, radix).map_err(|_| ())?; 289 | $num::new(parse).ok_or(()) 290 | } 291 | } 292 | 293 | impl ::core::str::FromStr for $num { 294 | type Err = ::FromStrRadixErr; 295 | 296 | fn from_str(s: &str) -> Result { 297 | ::from_str_radix(s, 10) 298 | } 299 | } 300 | 301 | impl Shr for $num { 302 | type Output = $num; 303 | 304 | fn shr(self, rhs: usize) -> Self::Output { 305 | $num::new(self.value() >> rhs).unwrap() 306 | } 307 | } 308 | 309 | impl Shl for $num { 310 | type Output = $num; 311 | 312 | fn shl(self, rhs: usize) -> Self::Output { 313 | $num::new(self.value() << rhs).unwrap() 314 | } 315 | } 316 | 317 | impl ShrAssign for $num { 318 | fn shr_assign(&mut self, rhs: usize) { 319 | let got = *self >> rhs; 320 | *self = got; 321 | } 322 | } 323 | 324 | impl ShlAssign for $num { 325 | fn shl_assign(&mut self, rhs: usize) { 326 | let got = *self << rhs; 327 | *self = got; 328 | } 329 | } 330 | 331 | impl Bounded for $num { 332 | fn min_value() -> Self { 333 | $num::new(Self::MIN).unwrap() 334 | } 335 | 336 | fn max_value() -> Self { 337 | $num::new(Self::MAX).unwrap() 338 | } 339 | } 340 | 341 | impl BitAnd for $num { 342 | type Output = $num; 343 | 344 | fn bitand(self, rhs: Self) -> Self::Output { 345 | $num(self.0 & rhs.0) 346 | } 347 | } 348 | 349 | impl BitXor for $num { 350 | type Output = $num; 351 | 352 | fn bitxor(self, rhs: Self) -> Self::Output { 353 | $num(self.0 ^ rhs.0) 354 | } 355 | } 356 | 357 | impl BitXorAssign for $num { 358 | fn bitxor_assign(&mut self, rhs: Self) { 359 | self.0 ^= rhs.0 360 | } 361 | } 362 | 363 | impl BitAndAssign for $num { 364 | fn bitand_assign(&mut self, rhs: Self) { 365 | self.0 &= rhs.0 366 | } 367 | } 368 | 369 | impl BitOr for $num { 370 | type Output = Self; 371 | 372 | fn bitor(self, rhs: Self) -> Self::Output { 373 | $num(self.0 | rhs.0) 374 | } 375 | } 376 | 377 | impl BitOrAssign for $num { 378 | fn bitor_assign(&mut self, rhs: Self) { 379 | self.0 |= rhs.0; 380 | } 381 | } 382 | }; 383 | } 384 | 385 | /// Create a type for representing unsigned integers of sizes not provided by 386 | /// rust 387 | macro_rules! new_unsigned_types { 388 | ( 389 | $($name: ident($count: literal, $inner: ty)),* 390 | ) => { 391 | $( 392 | 393 | #[doc = concat!("An unsigned integer which contains ", stringify!($count), " bits")] 394 | #[allow(non_camel_case_types)] 395 | #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] 396 | pub struct $name($inner); 397 | 398 | always_valid!($name); 399 | 400 | impl Debug for $name { 401 | fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { 402 | f.write_fmt(format_args!("{}", self.0)) 403 | } 404 | } 405 | 406 | impl Display for $name { 407 | fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { 408 | f.write_fmt(format_args!("{}", self.0)) 409 | } 410 | } 411 | 412 | #[cfg(feature = "serde")] 413 | impl serde::Serialize for $name { 414 | fn serialize(&self, serializer: S) -> Result 415 | where 416 | S: Serializer, 417 | { 418 | self.value().serialize(serializer) 419 | } 420 | } 421 | 422 | #[cfg(feature = "serde")] 423 | impl <'de> serde::Deserialize<'de> for $name { 424 | fn deserialize(deserializer: D) -> Result 425 | where 426 | D: Deserializer<'de>, 427 | { 428 | let inner = <$inner>::deserialize(deserializer)?; 429 | $name::new(inner).ok_or(serde::de::Error::custom("invalid size")) 430 | } 431 | } 432 | 433 | #[doc = concat!("Produce a value of type ", stringify!($name))] 434 | /// 435 | /// This macro checks at compile-time that it fits. To check at run-time see the 436 | #[doc = concat!("[`", stringify!($name), "::new`] function.")] 437 | #[macro_export] 438 | macro_rules! $name { 439 | ($value: literal) => { 440 | { 441 | const VALUE: $inner = $value; 442 | 443 | // this is always valid because we have one more bit than we need in $inner 444 | // type 445 | const _: () = assert!($crate::$name::MAX >= VALUE, "The provided value is too large"); 446 | unsafe {$crate::$name::new_unchecked(VALUE)} 447 | } 448 | }; 449 | } 450 | 451 | 452 | // SAFETY: 453 | // This is correct (guaranteed by macro arguments) 454 | unsafe impl BitCount for $name { 455 | /// The number of bits this type takes up 456 | /// 457 | /// Note that this is the conceptual amount it needs in a bit struct, not the amount it 458 | /// will use as its own variable on the stack. 459 | const COUNT: usize = $count; 460 | } 461 | 462 | impl $name { 463 | /// The largest value that can be stored 464 | pub const MAX: $inner = (1 << ($count)) - 1; 465 | /// The smallest value that can be stored 466 | pub const MIN: $inner = 0; 467 | 468 | #[doc = concat!("Create a new ", stringify!($name), " from an inner value")] 469 | /// 470 | /// This method does not do any checks that the value passed is valid. To check that, 471 | #[doc = concat!("use the [`", stringify!($name), "::new`] function.")] 472 | /// 473 | /// # Safety 474 | /// The value must be valid value of the given type. 475 | pub const unsafe fn new_unchecked(value: $inner) -> Self { 476 | Self(value) 477 | } 478 | 479 | #[doc = concat!("Create a new ", stringify!($name), " from an inner value")] 480 | /// 481 | /// This method checks that the inner value is valid, and return `None` if it isn't. 482 | pub fn new(value: $inner) -> Option { 483 | if (Self::MIN..=Self::MAX).contains(&value) { 484 | // SAFETY: 485 | // We've checked that this is safe to do in the above `if` 486 | Some(unsafe {Self::new_unchecked(value)}) 487 | } else { 488 | None 489 | } 490 | } 491 | 492 | /// Get the stored value 493 | pub const fn value(self) -> $inner { 494 | self.0 495 | } 496 | } 497 | 498 | impl Default for $name { 499 | fn default() -> Self { 500 | Self(0) 501 | } 502 | } 503 | 504 | num_traits!($name, $inner); 505 | 506 | impl FieldStorage for $name { 507 | type StoredType = $inner; 508 | 509 | fn inner_raw(self) -> Self::StoredType { 510 | self.0 511 | } 512 | } 513 | )* 514 | }; 515 | } 516 | 517 | new_signed_types!( 518 | i2(2, u8, i8), 519 | i3(3, u8, i8), 520 | i4(4, u8, i8), 521 | i5(5, u8, i8), 522 | i6(6, u8, i8), 523 | i7(7, u8, i8), 524 | i9(9, u16, i16), 525 | i10(10, u16, i16), 526 | i11(11, u16, i16), 527 | i12(12, u16, i16), 528 | i13(13, u16, i16), 529 | i14(14, u16, i16), 530 | i15(15, u16, i16), 531 | i17(17, u32, i32), 532 | i18(18, u32, i32), 533 | i19(19, u32, i32), 534 | i20(20, u32, i32), 535 | i21(21, u32, i32), 536 | i22(22, u32, i32), 537 | i23(23, u32, i32), 538 | i24(24, u32, i32), 539 | i25(25, u32, i32), 540 | i26(26, u32, i32), 541 | i27(27, u32, i32), 542 | i28(28, u32, i32), 543 | i29(29, u32, i32), 544 | i30(30, u32, i32), 545 | i31(31, u32, i32), 546 | i33(33, u64, i64), 547 | i34(34, u64, i64), 548 | i35(35, u64, i64), 549 | i36(36, u64, i64), 550 | i37(37, u64, i64), 551 | i38(38, u64, i64), 552 | i39(39, u64, i64), 553 | i40(40, u64, i64), 554 | i41(41, u64, i64), 555 | i42(42, u64, i64), 556 | i43(43, u64, i64), 557 | i44(44, u64, i64), 558 | i45(45, u64, i64), 559 | i46(46, u64, i64), 560 | i47(47, u64, i64), 561 | i48(48, u64, i64), 562 | i49(49, u64, i64), 563 | i50(50, u64, i64), 564 | i51(51, u64, i64), 565 | i52(52, u64, i64), 566 | i53(53, u64, i64), 567 | i54(54, u64, i64), 568 | i55(55, u64, i64), 569 | i56(56, u64, i64), 570 | i57(57, u64, i64), 571 | i58(58, u64, i64), 572 | i59(59, u64, i64), 573 | i60(60, u64, i64), 574 | i61(61, u64, i64), 575 | i62(62, u64, i64), 576 | i63(63, u64, i64) 577 | ); 578 | 579 | new_unsigned_types!( 580 | u1(1, u8), 581 | u2(2, u8), 582 | u3(3, u8), 583 | u4(4, u8), 584 | u5(5, u8), 585 | u6(6, u8), 586 | u7(7, u8), 587 | u9(9, u16), 588 | u10(10, u16), 589 | u11(11, u16), 590 | u12(12, u16), 591 | u13(13, u16), 592 | u14(14, u16), 593 | u15(15, u16), 594 | u17(17, u32), 595 | u18(18, u32), 596 | u19(19, u32), 597 | u20(20, u32), 598 | u21(21, u32), 599 | u22(22, u32), 600 | u23(23, u32), 601 | u24(24, u32), 602 | u25(25, u32), 603 | u26(26, u32), 604 | u27(27, u32), 605 | u28(28, u32), 606 | u29(29, u32), 607 | u30(30, u32), 608 | u31(31, u32), 609 | u33(33, u64), 610 | u34(34, u64), 611 | u35(35, u64), 612 | u36(36, u64), 613 | u37(37, u64), 614 | u38(38, u64), 615 | u39(39, u64), 616 | u40(40, u64), 617 | u41(41, u64), 618 | u42(42, u64), 619 | u43(43, u64), 620 | u44(44, u64), 621 | u45(45, u64), 622 | u46(46, u64), 623 | u47(47, u64), 624 | u48(48, u64), 625 | u49(49, u64), 626 | u50(50, u64), 627 | u51(51, u64), 628 | u52(52, u64), 629 | u53(53, u64), 630 | u54(54, u64), 631 | u55(55, u64), 632 | u56(56, u64), 633 | u57(57, u64), 634 | u58(58, u64), 635 | u59(59, u64), 636 | u60(60, u64), 637 | u61(61, u64), 638 | u62(62, u64), 639 | u63(63, u64) 640 | ); 641 | 642 | /// Implement functions for converting to/from byte arrays 643 | /// 644 | /// Used for our numeric types that are an integer number of bytes. 645 | macro_rules! byte_from_impls { 646 | ($($kind: ident: $super_kind: ty)*) => { 647 | $( 648 | impl $kind { 649 | /// The size of byte array equal to this value 650 | const ARR_SIZE: usize = <$kind>::COUNT / 8; 651 | /// The size of byte array equal to the underlying storage for this value 652 | const SUPER_BYTES: usize = ::core::mem::size_of::<$super_kind>(); 653 | /// Convert from an array of bytes, in big-endian order 654 | pub fn from_be_bytes(bytes: [u8; Self::ARR_SIZE]) -> Self { 655 | let mut res_bytes = [0_u8; Self::SUPER_BYTES]; 656 | for (set, &get) in res_bytes.iter_mut().rev().zip(bytes.iter().rev()) { 657 | *set = get; 658 | } 659 | Self(<$super_kind>::from_be_bytes(res_bytes)) 660 | } 661 | 662 | /// Convert `self` into an array of bytes, in big-endian order 663 | pub fn to_be_bytes(self) -> [u8; Self::ARR_SIZE] { 664 | let mut res = [0; Self::ARR_SIZE]; 665 | let inner_bytes = self.0.to_be_bytes(); 666 | for (&get, set) in inner_bytes.iter().rev().zip(res.iter_mut().rev()) { 667 | *set = get; 668 | } 669 | res 670 | } 671 | 672 | /// Convert from an array of bytes, in little-endian order 673 | pub fn from_le_bytes(bytes: [u8; Self::ARR_SIZE]) -> Self { 674 | let mut res_bytes = [0_u8; Self::SUPER_BYTES]; 675 | for (set, &get) in res_bytes.iter_mut().zip(bytes.iter()) { 676 | *set = get; 677 | } 678 | Self(<$super_kind>::from_le_bytes(res_bytes)) 679 | } 680 | 681 | /// Convert `self` into an array of bytes, in little-endian order 682 | pub fn to_le_bytes(self) -> [u8; Self::ARR_SIZE] { 683 | let mut res = [0; Self::ARR_SIZE]; 684 | let inner_bytes = self.0.to_le_bytes(); 685 | for (&get, set) in inner_bytes.iter().zip(res.iter_mut()) { 686 | *set = get; 687 | } 688 | res 689 | } 690 | } 691 | 692 | impl From for $kind { 693 | fn from(byte: u8) -> Self { 694 | let inner = <$super_kind>::from(byte); 695 | $kind(inner) 696 | } 697 | } 698 | )* 699 | }; 700 | } 701 | 702 | byte_from_impls! { 703 | u24: u32 704 | u40: u64 705 | u48: u64 706 | u56: u64 707 | i24: u32 708 | i40: u64 709 | i48: u64 710 | i56: u64 711 | } 712 | 713 | impl u1 { 714 | /// The 1-bit representation of true (1) 715 | pub const TRUE: Self = Self(1); 716 | /// The 1-bit representation of false (0) 717 | pub const FALSE: Self = Self(0); 718 | 719 | /// Get the opposite of this value (i.e. `TRUE` <--> `FALSE`) 720 | #[must_use] 721 | pub const fn toggle(self) -> Self { 722 | match self { 723 | Self::FALSE => Self::TRUE, 724 | _ => Self::FALSE, 725 | } 726 | } 727 | } 728 | 729 | /// Implement `BitsFitIn` for the given pair of types, using the given method 730 | macro_rules! bits_fit_in_impl { 731 | ($basety:ty => $target:ty : from) => { 732 | impl BitsFitIn<$target> for $basety { 733 | fn fit(self) -> $target { 734 | self.inner_raw().into() 735 | } 736 | } 737 | }; 738 | ($basety:ty => $target:ty : new_unchecked) => { 739 | impl BitsFitIn<$target> for $basety { 740 | fn fit(self) -> $target { 741 | // Safety: 742 | // The caller of this macro should only implement it with safe conversions 743 | unsafe { <$target>::new_unchecked(self.inner_raw().into()) } 744 | } 745 | } 746 | }; 747 | } 748 | 749 | /// Implement `BitsFitIn` easily for a large number of unsigned types 750 | macro_rules! bits_fit_in_impls { 751 | () => {}; 752 | ( 753 | // The types we generate from in this pass 754 | ($basety:ty: $funcname:ident, $extra_ty:ty) 755 | // The remaining target types 756 | $( , 757 | ($first_target:ty: $target_funcname:ident $(, $extra_sources:ty)* $(,)?) 758 | )* $(,)? 759 | ) => { 760 | bits_fit_in_impl!($basety => $basety: $funcname); 761 | $( 762 | bits_fit_in_impl!($basety => $first_target: $target_funcname); 763 | bits_fit_in_impl!($extra_ty => $first_target: $target_funcname); 764 | )* 765 | bits_fit_in_impls!($(($first_target: $target_funcname $(, $extra_sources)*)),*); 766 | } 767 | } 768 | 769 | bits_fit_in_impls!( 770 | (u1: new_unchecked, bool), 771 | (u2: new_unchecked, i2), 772 | (u3: new_unchecked, i3), 773 | (u4: new_unchecked, i4), 774 | (u5: new_unchecked, i5), 775 | (u6: new_unchecked, i6), 776 | (u7: new_unchecked, i7), 777 | (u8: from, i8), 778 | (u9: new_unchecked, i9), 779 | (u10: new_unchecked, i10), 780 | (u11: new_unchecked, i11), 781 | (u12: new_unchecked, i12), 782 | (u13: new_unchecked, i13), 783 | (u14: new_unchecked, i14), 784 | (u15: new_unchecked, i15), 785 | (u16: from, i16), 786 | (u17: new_unchecked, i17), 787 | (u18: new_unchecked, i18), 788 | (u19: new_unchecked, i19), 789 | (u20: new_unchecked, i20), 790 | (u21: new_unchecked, i21), 791 | (u22: new_unchecked, i22), 792 | (u23: new_unchecked, i23), 793 | (u24: new_unchecked, i24), 794 | (u25: new_unchecked, i25), 795 | (u26: new_unchecked, i26), 796 | (u27: new_unchecked, i27), 797 | (u28: new_unchecked, i28), 798 | (u29: new_unchecked, i29), 799 | (u30: new_unchecked, i30), 800 | (u31: new_unchecked, i31), 801 | (u32: from, i32), 802 | (u33: new_unchecked, i33), 803 | (u34: new_unchecked, i34), 804 | (u35: new_unchecked, i35), 805 | (u36: new_unchecked, i36), 806 | (u37: new_unchecked, i37), 807 | (u38: new_unchecked, i38), 808 | (u39: new_unchecked, i39), 809 | (u40: new_unchecked, i40), 810 | (u41: new_unchecked, i41), 811 | (u42: new_unchecked, i42), 812 | (u43: new_unchecked, i43), 813 | (u44: new_unchecked, i44), 814 | (u45: new_unchecked, i45), 815 | (u46: new_unchecked, i46), 816 | (u47: new_unchecked, i47), 817 | (u48: new_unchecked, i48), 818 | (u49: new_unchecked, i49), 819 | (u50: new_unchecked, i50), 820 | (u51: new_unchecked, i51), 821 | (u52: new_unchecked, i52), 822 | (u53: new_unchecked, i53), 823 | (u54: new_unchecked, i54), 824 | (u55: new_unchecked, i55), 825 | (u56: new_unchecked, i56), 826 | (u57: new_unchecked, i57), 827 | (u58: new_unchecked, i58), 828 | (u59: new_unchecked, i59), 829 | (u60: new_unchecked, i60), 830 | (u61: new_unchecked, i61), 831 | (u62: new_unchecked, i62), 832 | (u63: new_unchecked, i63), 833 | (u64: from, i64), 834 | ); 835 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![doc = include_str!("../README.md")] 2 | #![no_std] 3 | 4 | use core::{ 5 | fmt::{Debug, Display}, 6 | marker::PhantomData, 7 | ops::{ 8 | Add, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, Mul, Rem, Shl, 9 | ShlAssign, Shr, ShrAssign, Sub, 10 | }, 11 | }; 12 | 13 | use num_traits::{Bounded, Num, One, Zero}; 14 | /// Import serde here so we can reference it inside macros 15 | #[doc(hidden)] 16 | #[cfg(feature = "serde")] 17 | pub use serde; 18 | 19 | mod types; 20 | 21 | pub use types::{ 22 | i10, i11, i12, i13, i14, i15, i17, i18, i19, i2, i20, i21, i22, i23, i24, i25, i26, i27, i28, 23 | i29, i3, i30, i31, i33, i34, i35, i36, i37, i38, i39, i4, i40, i41, i42, i43, i44, i45, i46, 24 | i47, i48, i49, i5, i50, i51, i52, i53, i54, i55, i56, i57, i58, i59, i6, i60, i61, i62, i63, 25 | i7, i9, u1, u10, u11, u12, u13, u14, u15, u17, u18, u19, u2, u20, u21, u22, u23, u24, u25, u26, 26 | u27, u28, u29, u3, u30, u31, u33, u34, u35, u36, u37, u38, u39, u4, u40, u41, u42, u43, u44, 27 | u45, u46, u47, u48, u49, u5, u50, u51, u52, u53, u54, u55, u56, u57, u58, u59, u6, u60, u61, 28 | u62, u63, u7, u9, 29 | }; 30 | 31 | /// [`UnsafeStorage`] is used to mark that there are some arbitrary invariants 32 | /// which must be maintained in storing its inner value. Therefore, creation and 33 | /// modifying of the inner value is an "unsafe" behavior. Although it might not 34 | /// be unsafe in traditional Rust terms (no memory unsafety), behavior might be 35 | /// "undefined"—or at least undocumented, because invariants are expected to be 36 | /// upheld. 37 | /// 38 | /// This is useful in macros which do not encapsulate their storage in modules. 39 | /// This makes the macros for the end-user more ergonomic, as they can use the 40 | /// macro multiple times in a single module. 41 | #[repr(transparent)] 42 | #[derive(Copy, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)] 43 | pub struct UnsafeStorage(T); 44 | 45 | impl UnsafeStorage { 46 | /// Create a new `UnsafeStorage` with the given inner value. 47 | /// 48 | /// # Safety 49 | /// - See the broader scope that this is called in and which invariants are 50 | /// mentioned 51 | pub const unsafe fn new_unsafe(inner: T) -> Self { 52 | Self(inner) 53 | } 54 | 55 | /// Mutably access the value stored inside 56 | /// 57 | /// # Safety 58 | /// This should be a safe operation assuming that when modifying T to T', 59 | /// `UnsafeStorage::new_unsafe`(T') is safe 60 | pub unsafe fn as_ref_mut(&mut self) -> &mut T { 61 | &mut self.0 62 | } 63 | } 64 | 65 | impl AsRef for UnsafeStorage { 66 | /// Access the value stored inside 67 | fn as_ref(&self) -> &T { 68 | &self.0 69 | } 70 | } 71 | 72 | impl UnsafeStorage { 73 | /// Access the value stored inside 74 | pub const fn inner(&self) -> T { 75 | self.0 76 | } 77 | } 78 | 79 | /// A trait which defines how many bits are needed to store a struct. 80 | /// 81 | /// # Safety 82 | /// Define `Num` as `{i,u}{8,16,32,64,128}`. 83 | /// - when calling `core::mem::transmute` on `Self`, only bits [0, COUNT) can be 84 | /// non-zero 85 | /// - `TryFrom` produces `Some(x)` <=> `core::mem::transmute(num)` produces 86 | /// a valid Self(x) 87 | /// - `TryFrom` produces `None` <=> `core::mem::transmute(num)` produces an 88 | /// invalid state for Self 89 | pub unsafe trait BitCount { 90 | /// The number of bits associated with this type 91 | const COUNT: usize; 92 | } 93 | 94 | /// A type which can be a field of a `bit_struct` 95 | pub trait FieldStorage { 96 | /// The type this field stores as 97 | type StoredType; 98 | /// Get the raw representation of this value 99 | fn inner_raw(self) -> Self::StoredType; 100 | } 101 | 102 | /// A conversion type for fitting the bits of one type into the bits of another 103 | /// type 104 | /// 105 | /// This differs from [`Into`] because the value may not be semantically the 106 | /// same, this trait just asserts that the conversion can be done injectively. 107 | /// 108 | /// The default implementation for our numeric types is to zero-extend the bits 109 | /// to fit the target size. 110 | pub trait BitsFitIn { 111 | /// Fits `self` into the target type 112 | fn fit(self) -> T; 113 | } 114 | 115 | /// Check whether the underlying bits are valid 116 | /// 117 | /// The type implementing this trait checks if the value stored in a bit 118 | /// representation of type `P` is a valid representation of this type. The 119 | /// [`enums`] macro implements this type for all of the integer-byte-width types 120 | /// from this crate. 121 | /// 122 | /// # Safety 123 | /// 124 | /// The [`ValidCheck::is_valid`] function must be correctly implemented or else 125 | /// other functions in this crate won't work correctly. Implementation of this 126 | /// trait is preferably done by public macros in this crate, which will 127 | /// implement it correctly. 128 | pub unsafe trait ValidCheck

{ 129 | /// Set this to true if, at compile-time, we can tell that all bit 130 | /// representations which contain the appropriate number of bits are valid 131 | /// representations of this type 132 | const ALWAYS_VALID: bool = false; 133 | /// Return whether or not the underlying bits of `P` are valid 134 | /// representation of this type 135 | fn is_valid(_input: P) -> bool { 136 | true 137 | } 138 | } 139 | 140 | /// A struct which allows for getting/setting a given property 141 | pub struct GetSet<'a, P, T, const START: usize, const STOP: usize> { 142 | /// The referenced bitfield type. 143 | parent: &'a mut P, 144 | /// The type in the get/set operations 145 | _phantom: PhantomData<&'a mut T>, 146 | } 147 | 148 | impl<'a, P, T, const START: usize, const STOP: usize> GetSet<'a, P, T, START, STOP> { 149 | /// The bit offset at which this `GetSet` instance starts 150 | pub const fn start(&self) -> usize { 151 | START 152 | } 153 | 154 | /// The bit offset at which this `GetSet` instance ends 155 | pub const fn stop(&self) -> usize { 156 | STOP 157 | } 158 | } 159 | 160 | impl< 161 | 'a, 162 | P: Num + Bounded + ShlAssign + ShrAssign + BitCount, 163 | T, 164 | const START: usize, 165 | const STOP: usize, 166 | > GetSet<'a, P, T, START, STOP> 167 | { 168 | /// Create a new [`GetSet`]. This should be called from methods generated by 169 | /// the [`bit_struct`] macro 170 | pub fn new(parent: &'a mut P) -> Self { 171 | Self { 172 | parent, 173 | _phantom: PhantomData::default(), 174 | } 175 | } 176 | 177 | /// Get a mask of `STOP-START + 1` length. This doesn't use the shift left 178 | /// and subtract one trick because of the special case where `(0b1 << 179 | /// (STOP - START + 1)) - 1` will cause an overflow 180 | // Because `GetSet` has a lot of type parameters, it's easiest to be able to invoke this method 181 | // directly on a value instead of having to match the type parameters. 182 | #[allow(clippy::unused_self)] 183 | fn mask(&self) -> P { 184 | let num_bits = P::COUNT; 185 | let mut max_value = P::max_value(); 186 | let keep_bits = STOP - START + 1; 187 | 188 | max_value >>= num_bits - keep_bits; 189 | max_value 190 | } 191 | } 192 | 193 | impl< 194 | 'a, 195 | P: Num 196 | + Shl 197 | + Shr 198 | + ShlAssign 199 | + ShrAssign 200 | + Bounded 201 | + BitAnd 202 | + Copy 203 | + BitCount, 204 | T: ValidCheck

, 205 | const START: usize, 206 | const STOP: usize, 207 | > GetSet<'a, P, T, START, STOP> 208 | { 209 | /// Get the property this `GetSet` points at 210 | pub fn get(&self) -> T { 211 | let section = self.get_raw(); 212 | // Safety: 213 | // This is guaranteed to be safe because the underlying storage must be bigger 214 | // than any fields stored within 215 | unsafe { core::mem::transmute_copy(§ion) } 216 | } 217 | 218 | /// Returns true if the memory this `GetSet` points at is a valid 219 | /// representation of `T` 220 | pub fn is_valid(&self) -> bool { 221 | let section = self.get_raw(); 222 | T::is_valid(section) 223 | } 224 | 225 | /// Get the raw bits being pointed at, without type conversion nor any form 226 | /// of validation 227 | pub fn get_raw(&self) -> P { 228 | let parent = *self.parent; 229 | let mask = self.mask(); 230 | (parent >> START) & mask 231 | } 232 | } 233 | 234 | impl<'a, P, T, const START: usize, const STOP: usize> GetSet<'a, P, T, START, STOP> 235 | where 236 | T: FieldStorage + BitsFitIn

, 237 | P: Num 238 | + Shl 239 | + Copy 240 | + BitOrAssign 241 | + BitXorAssign 242 | + BitAnd 243 | + ShlAssign 244 | + ShrAssign 245 | + PartialOrd 246 | + Bounded 247 | + Sized 248 | + BitCount, 249 | { 250 | /// Set the property in the slice being pointed to by this `GetSet` 251 | pub fn set(&mut self, value: T) { 252 | // SAFETY: 253 | // This is safe because we produce it from a valid value of `T`, so we meet the 254 | // safety condition on `set_raw` 255 | unsafe { self.set_raw(value.fit()) } 256 | } 257 | 258 | /// Set the field to a raw value. 259 | /// # Safety 260 | /// value must be a valid representation of the field. i.e., 261 | /// `core::mem::transmute` between P and T must be defined. 262 | pub unsafe fn set_raw(&mut self, value: P) { 263 | let mask = self.mask(); 264 | let mask_shifted = mask << START; 265 | 266 | // zero out parent 267 | *self.parent |= mask_shifted; 268 | *self.parent ^= mask_shifted; 269 | 270 | let to_set = value & mask; 271 | *self.parent |= to_set << START; 272 | } 273 | } 274 | 275 | /// A trait that all bit structs implement 276 | /// 277 | /// See the [`bit_struct`] macro for more details. 278 | pub trait BitStruct { 279 | /// The underlying type used to store the bit struct 280 | type Kind; 281 | /// Produce a bit struct from the given underlying storage, without checking 282 | /// for validity. 283 | /// 284 | /// # Safety 285 | /// 286 | /// The caller is responsible for verifying that this value is a valid value 287 | /// for the bit struct. 288 | /// 289 | /// If this is guaranteed to be safe (i.e. all possibly inputs for `value` 290 | /// are valid), then the bit struct will also implement [`BitStructExt`] 291 | /// which has the [`BitStructExt::exact_from`] method, that you should 292 | /// use instead. 293 | unsafe fn from_unchecked(value: Self::Kind) -> Self; 294 | } 295 | 296 | /// An extension trait for bit structs which can be safely made from any value 297 | /// in their underlying storage type. 298 | pub trait BitStructExt: BitStruct { 299 | /// Produce a bit struct from the given underlying storage 300 | fn exact_from(value: Self::Kind) -> Self; 301 | } 302 | 303 | impl> BitStructExt for T { 304 | fn exact_from(value: Self::Kind) -> Self { 305 | // SAFETY: 306 | // This is safe because this method only exists for bitfields for which it is 307 | // always safe to call `from_unchecked` 308 | unsafe { Self::from_unchecked(value) } 309 | } 310 | } 311 | 312 | #[doc(hidden)] 313 | #[macro_export] 314 | macro_rules! impl_fields { 315 | ($on: expr, $kind: ty =>[$($first_field_meta: meta),*], $head_field: ident, $head_actual: ty $(, [$($field_meta: meta),*], $field: ident, $actual: ty)*) => { 316 | $(#[$first_field_meta])* 317 | pub fn $head_field(&mut self) -> $crate::GetSet<'_, $kind, $head_actual, {$on - <$head_actual as $crate::BitCount>::COUNT}, {$on - 1}> { 318 | $crate::GetSet::new(unsafe {self.0.as_ref_mut()}) 319 | } 320 | 321 | $crate::impl_fields!($on - <$head_actual as $crate::BitCount>::COUNT, $kind => $([$($field_meta),*], $field, $actual),*); 322 | }; 323 | ($on: expr, $kind: ty =>) => {}; 324 | } 325 | 326 | /// Helper macro 327 | #[doc(hidden)] 328 | #[macro_export] 329 | macro_rules! bit_struct_impl { 330 | ( 331 | $(#[$meta: meta])* 332 | $struct_vis: vis struct $name: ident ($kind: ty) { 333 | $( 334 | $(#[$field_meta: meta])* 335 | $field: ident: $actual: ty 336 | ),* $(,)? 337 | } 338 | ) => { 339 | 340 | impl $name { 341 | 342 | /// Creates an empty struct. This may or may not be valid 343 | pub unsafe fn empty() -> Self { 344 | unsafe { Self::from_unchecked(<$kind as $crate::BitStructZero>::bs_zero()) } 345 | } 346 | 347 | #[doc = concat!("Returns a valid representation for [`", stringify!($name), "`] where all values are")] 348 | /// the defaults 349 | /// 350 | /// This is different than [`Self::default()`], because the actual default implementation 351 | /// might not be composed of only the defaults of the given fields. 352 | pub fn of_defaults() -> Self { 353 | let mut res = unsafe { Self::from_unchecked(<$kind as $crate::BitStructZero>::bs_zero()) }; 354 | $( 355 | res.$field().set(Default::default()); 356 | )* 357 | res 358 | } 359 | } 360 | 361 | impl ::core::fmt::Debug for $name { 362 | fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> core::fmt::Result { 363 | let mut copied = *self; 364 | f.debug_struct(stringify!($name)) 365 | $( 366 | .field(stringify!($field), &copied.$field().get()) 367 | )* 368 | .finish() 369 | } 370 | } 371 | }; 372 | } 373 | 374 | /// `serde` feature is not provided, so don't implement it 375 | #[doc(hidden)] 376 | #[macro_export] 377 | #[cfg(not(feature = "serde"))] 378 | macro_rules! bit_struct_serde_impl { 379 | ( 380 | $(#[$meta:meta])* 381 | $struct_vis:vis struct 382 | $name:ident($kind:ty) { $($(#[$field_meta:meta])* $field:ident : $actual:ty),* $(,)? } 383 | ) => {}; 384 | } 385 | /// `serde` feature is provided, so implement it 386 | #[doc(hidden)] 387 | #[macro_export] 388 | #[cfg(feature = "serde")] 389 | macro_rules! bit_struct_serde_impl { 390 | ( 391 | $(#[$meta:meta])* 392 | $struct_vis: vis struct $name: ident ($kind: ty) { 393 | $( 394 | $(#[$field_meta:meta])* 395 | $field: ident: $actual: ty 396 | ),* $(,)? 397 | } 398 | ) => { 399 | #[allow(clippy::used_underscore_binding)] 400 | impl $crate::serde::Serialize for $name { 401 | fn serialize(&self, serializer: S) -> Result where S: $crate::serde::Serializer { 402 | use $crate::serde::ser::SerializeStruct; 403 | 404 | let mut v = *self; 405 | 406 | let mut serializer = serializer.serialize_struct( 407 | stringify!($name), 408 | $crate::count_idents!( 0, [$( $field ),*] ), 409 | )?; 410 | $( 411 | serializer.serialize_field( 412 | stringify!($field), 413 | &v.$field().get() 414 | )?; 415 | )* 416 | serializer.end() 417 | } 418 | } 419 | 420 | #[allow(clippy::used_underscore_binding)] 421 | impl<'de> $crate::serde::Deserialize<'de> for $name { 422 | fn deserialize(deserializer: D) -> Result where D: $crate::serde::Deserializer<'de> { 423 | 424 | use $crate::serde::de::{self, Deserialize, Deserializer, MapAccess, SeqAccess, Visitor}; 425 | use ::core::fmt; 426 | 427 | const FIELDS: &'static [&'static str] = &[ $( stringify!( $field ) ),* ]; 428 | 429 | #[allow(non_camel_case_types)] 430 | enum Fields { $( $field ),* } 431 | impl<'de> Deserialize<'de> for Fields { 432 | fn deserialize>(deserializer: D) -> Result { 433 | struct FieldVisitor; 434 | impl<'de> Visitor<'de> for FieldVisitor { 435 | type Value = Fields; 436 | 437 | fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 438 | f.write_str(stringify!( $( $field ),* )) 439 | } 440 | 441 | fn visit_str(self, value: &str) -> Result { 442 | match value { 443 | $( stringify!( $field ) => Ok(Fields::$field), )* 444 | _ => Err(de::Error::unknown_field(value, FIELDS)), 445 | } 446 | } 447 | } 448 | 449 | deserializer.deserialize_identifier(FieldVisitor) 450 | } 451 | } 452 | 453 | struct BitStructVisitor; 454 | impl<'de> Visitor<'de> for BitStructVisitor { 455 | type Value = $name; 456 | 457 | fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 458 | f.write_str(concat!("struct ", stringify!($name))) 459 | } 460 | 461 | fn visit_map>(self, mut map: V) -> Result<$name, V::Error> { 462 | $( let mut $field: Option<$actual> = None; )* 463 | while let Some(key) = map.next_key::()? { 464 | match key { 465 | $( Fields::$field => { 466 | if $field.is_some() { 467 | return Err(de::Error::duplicate_field(stringify!($field))); 468 | } 469 | $field = Some(map.next_value()?); 470 | },)* 471 | } 472 | } 473 | $( 474 | let $field = $field.ok_or_else(|| de::Error::missing_field(stringify!($field)))?; 475 | )* 476 | Ok($name::new( $( $field ),* )) 477 | } 478 | 479 | fn visit_seq>(self, mut seq: V) -> Result<$name, V::Error> { 480 | let mut count = 0; 481 | $( 482 | let $field = seq.next_element()? 483 | .ok_or_else(|| de::Error::invalid_length(count, &self))?; 484 | count += 1; 485 | )* 486 | Ok($name::new( $( $field ),* )) 487 | } 488 | } 489 | deserializer.deserialize_struct(stringify!($name), FIELDS, BitStructVisitor) 490 | } 491 | } 492 | } 493 | } 494 | 495 | /// A bit struct which has a zero value we can get 496 | pub trait BitStructZero: Zero { 497 | /// Get a zero value for this bit struct 498 | fn bs_zero() -> Self { 499 | Self::zero() 500 | } 501 | } 502 | 503 | impl BitStructZero for T {} 504 | 505 | // the main is actually needed 506 | 507 | #[allow(clippy::needless_doctest_main)] 508 | /// Create a bit struct. 509 | /// 510 | /// 511 | /// This macro can only be used once for each module. 512 | /// This is because the macro creates sub-module to limit access to certain 513 | /// unsafe access. In the macro, bit-structs can be defined just like a struct 514 | /// outside of the the macro. The catch is a **base type** must be specified. 515 | /// Valid base types are u{8,16,32,64,128}. The elements stored in the struct 516 | /// are statically guaranteed to not exceed the number of bits in the base type. 517 | /// This means we cannot store a `u16` in a `u8`, but it also means we cannot 518 | /// store 9 `u1`s in a u8. 519 | /// 520 | /// Elements start at the top of the number (for a u16 this would be the 15th 521 | /// bit) and progress down. 522 | /// 523 | /// # Example 524 | /// ``` 525 | /// bit_struct::enums! { 526 | /// /// The default value for each enum is always the first 527 | /// pub ThreeVariants { Zero, One, Two } 528 | /// 529 | /// /// This is syntax to set the default value to Cat 530 | /// pub Animal(Cat) { Cow, Bird, Cat, Dog } 531 | /// 532 | /// pub Color { Orange, Red, Blue, Yellow, Green } 533 | /// } 534 | /// 535 | /// bit_struct::bit_struct! { 536 | /// /// We can write documentation for the struct here. 537 | /// struct BitStruct1 (u16){ 538 | /// /// a 1 bit element. This is stored in u16[15] 539 | /// a: bit_struct::u1, 540 | /// 541 | /// /// This is calculated to take up 2 bits. This is stored in u16[13..=14] 542 | /// variant: ThreeVariants, 543 | /// 544 | /// /// This also takes 2 bits. This is stored in u16[11..=12] 545 | /// animal: Animal, 546 | /// 547 | /// /// This takes up 3 bits. This is stored u16[8..=10] 548 | /// color: Color, 549 | /// } 550 | /// 551 | /// struct BitStruct2(u32) { 552 | /// /// We could implement for this too. Note, this does not have a default 553 | /// a_color: Color, 554 | /// b: bit_struct::u3, 555 | /// } 556 | /// } 557 | /// 558 | /// fn main() { 559 | /// use std::convert::TryFrom; 560 | /// let mut bit_struct: BitStruct1 = BitStruct1::of_defaults(); 561 | /// 562 | /// assert_eq!(bit_struct.a().start(), 15); 563 | /// assert_eq!(bit_struct.a().stop(), 15); 564 | /// 565 | /// assert_eq!(bit_struct.color().start(), 8); 566 | /// assert_eq!(bit_struct.color().stop(), 10); 567 | /// 568 | /// assert_eq!( 569 | /// format!("{:?}", bit_struct), 570 | /// "BitStruct1 { a: 0, variant: Zero, animal: Cat, color: Orange }" 571 | /// ); 572 | /// assert_eq!(bit_struct.raw(), 4096); 573 | /// 574 | /// let reverse_bit_struct = BitStruct1::try_from(4096); 575 | /// assert_eq!( 576 | /// format!("{:?}", reverse_bit_struct), 577 | /// "Ok(BitStruct1 { a: 0, variant: Zero, animal: Cat, color: Orange })" 578 | /// ); 579 | /// 580 | /// // u3! macro provides a static assert that the number is not too large 581 | /// let mut other_struct = BitStruct2::new(Color::Green, bit_struct::u3!(0b101)); 582 | /// assert_eq!( 583 | /// format!("{:?}", other_struct), 584 | /// "BitStruct2 { a_color: Green, b: 5 }" 585 | /// ); 586 | /// 587 | /// assert_eq!(other_struct.a_color().get(), Color::Green); 588 | /// 589 | /// other_struct.a_color().set(Color::Red); 590 | /// 591 | /// assert_eq!(other_struct.a_color().get(), Color::Red); 592 | /// } 593 | /// ``` 594 | #[macro_export] 595 | macro_rules! bit_struct { 596 | ( 597 | $( 598 | $(#[$meta:meta])* 599 | $struct_vis: vis struct $name: ident ($kind: ty) { 600 | $( 601 | $(#[$field_meta:meta])* 602 | $field: ident: $actual: ty 603 | ),* $(,)? 604 | } 605 | )* 606 | ) => { 607 | $( 608 | $(#[$meta])* 609 | #[derive(Copy, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)] 610 | pub struct $name($crate::UnsafeStorage<$kind>); 611 | 612 | $crate::bit_struct_serde_impl! { 613 | $(#[$meta])* 614 | $struct_vis struct $name ($kind) { 615 | $( 616 | $(#[$field_meta])* 617 | $field: $actual 618 | ),* 619 | } 620 | } 621 | 622 | #[allow(clippy::used_underscore_binding)] 623 | impl TryFrom<$kind> for $name { 624 | type Error = (); 625 | fn try_from(elem: $kind) -> Result<$name, ()> { 626 | let mut res = unsafe{Self::from_unchecked(elem)}; 627 | $( 628 | if !res.$field().is_valid() { 629 | return Err(()); 630 | } 631 | )* 632 | Ok(res) 633 | } 634 | } 635 | 636 | #[allow(clippy::used_underscore_binding)] 637 | impl $crate::BitStruct<{$(<$actual as $crate::ValidCheck<$kind>>::ALWAYS_VALID &&)* true}> for $name { 638 | type Kind = $kind; 639 | 640 | unsafe fn from_unchecked(inner: $kind) -> Self { 641 | Self(unsafe {$crate::UnsafeStorage::new_unsafe(inner)}) 642 | } 643 | } 644 | 645 | #[allow(clippy::used_underscore_binding)] 646 | impl $name { 647 | 648 | unsafe fn from_unchecked(inner: $kind) -> Self { 649 | Self(unsafe {$crate::UnsafeStorage::new_unsafe(inner)}) 650 | } 651 | 652 | #[allow(clippy::too_many_arguments)] 653 | pub fn new($($field: $actual),*) -> Self { 654 | let mut res = unsafe { Self::from_unchecked(<$kind as $crate::BitStructZero>::bs_zero()) }; 655 | $( 656 | res.$field().set($field); 657 | )* 658 | res 659 | } 660 | 661 | pub fn raw(self) -> $kind { 662 | self.0.inner() 663 | } 664 | 665 | $crate::impl_fields!(<$kind as $crate::BitCount>::COUNT, $kind => $([$($field_meta),*], $field, $actual),*); 666 | } 667 | 668 | )* 669 | 670 | $( 671 | $crate::bit_struct_impl!( 672 | $(#[$meta])* 673 | $struct_vis struct $name ($kind) { 674 | $( 675 | $(#[$field_meta])* 676 | $field: $actual 677 | ),* 678 | } 679 | 680 | ); 681 | )* 682 | }; 683 | } 684 | 685 | #[doc(hidden)] 686 | #[macro_export] 687 | macro_rules! count_idents { 688 | ($on: expr, [$head: ident $(,$xs: ident)*]) => { 689 | $crate::count_idents!($on + 1, [$($xs),*]) 690 | }; 691 | ($on: expr, []) => { 692 | $on 693 | }; 694 | } 695 | 696 | /// Returns the index of the leading 1 in `num` 697 | /// 698 | /// Example: 699 | /// ``` 700 | /// # use bit_struct::bits; 701 | /// 702 | /// assert_eq!(bits(2), 2); 703 | /// assert_eq!(bits(3), 2); 704 | /// assert_eq!(bits(5), 3); 705 | /// assert_eq!(bits(32), 6); 706 | /// ``` 707 | pub const fn bits(num: usize) -> usize { 708 | /// Helper function for [`bits`] 709 | const fn helper(count: usize, on: usize) -> usize { 710 | // 0b11 = 3 log2_ceil(0b11) = 2 .. 2^2 711 | // 0b10 = 2 log2_ceil = 2 .. 2^1 712 | if on > 0 { 713 | helper(count + 1, on >> 1) 714 | } else { 715 | count 716 | } 717 | } 718 | 719 | helper(0, num) 720 | } 721 | 722 | /// `serde` feature is not provided, so don't implement it 723 | #[doc(hidden)] 724 | #[cfg(not(feature = "serde"))] 725 | #[macro_export] 726 | macro_rules! enum_serde_impl { 727 | ($enum_vis:vis $name:ident { $fst_field:ident $(, $field:ident)* }) => {}; 728 | } 729 | 730 | /// `serde` feature is provided, so implement it 731 | #[doc(hidden)] 732 | #[cfg(feature = "serde")] 733 | #[macro_export] 734 | macro_rules! enum_serde_impl { 735 | ($name:ident { $($field:ident),* }) => { 736 | impl $crate::serde::Serialize for $name { 737 | fn serialize(&self, serializer: S) -> Result { 738 | match self { 739 | $( 740 | Self::$field => { 741 | serializer.serialize_unit_variant( 742 | stringify!($name), 743 | *self as u32, 744 | stringify!($field), 745 | ) 746 | }, 747 | )* 748 | } 749 | } 750 | } 751 | impl<'de> $crate::serde::Deserialize<'de> for $name { 752 | fn deserialize(deserializer: D) -> Result where D: $crate::serde::Deserializer<'de> { 753 | use ::core::{fmt, result::Result::{self, Ok, Err}, convert::TryFrom}; 754 | use $crate::serde::de::{Deserialize, Deserializer, EnumAccess, VariantAccess, Visitor}; 755 | 756 | #[repr(u64)] 757 | enum Variants { $( $field ),* } 758 | impl TryFrom for Variants { 759 | type Error = (); 760 | 761 | fn try_from(v: u64) -> Result { 762 | if v < $crate::count_idents!(0, [$( $field ),*]) { 763 | // SAFETY: 764 | // This is safe because we're converting a `u64` to a `repr(u64)` 765 | // enum, and we've checked that the value is one of the variants. 766 | unsafe { core::mem::transmute(v) } 767 | } else { 768 | Err(()) 769 | } 770 | } 771 | } 772 | impl<'de> Deserialize<'de> for Variants { 773 | fn deserialize>(deserializer: D) -> Result { 774 | struct VariantsVisitor; 775 | impl<'de> Visitor<'de> for VariantsVisitor { 776 | type Value = Variants; 777 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 778 | formatter.write_str("variant identifier") 779 | } 780 | 781 | fn visit_u64(self, value: u64) -> Result { 782 | Variants::try_from(value) 783 | .map_err(|()| $crate::serde::de::Error::invalid_value( 784 | $crate::serde::de::Unexpected::Unsigned(value), 785 | &"variant index" 786 | )) 787 | } 788 | 789 | fn visit_str(self, value: &str) -> Result { 790 | match value { 791 | $( stringify!($field) => Ok(Variants::$field), )* 792 | _ => Err($crate::serde::de::Error::unknown_variant(value, VARIANTS)), 793 | } 794 | } 795 | } 796 | deserializer.deserialize_identifier(VariantsVisitor) 797 | } 798 | } 799 | 800 | struct EnumVisitor; 801 | impl<'de> Visitor<'de> for EnumVisitor { 802 | type Value = $name; 803 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 804 | formatter.write_str(concat!("enum ", stringify!($name))) 805 | } 806 | 807 | fn visit_enum>(self, data: A) -> Result { 808 | match data.variant()? { 809 | $( 810 | (Variants::$field, variant) => { 811 | let () = variant.unit_variant()?; 812 | Ok($name::$field) 813 | } 814 | ),* 815 | } 816 | } 817 | } 818 | const VARIANTS: &'static [&'static str] = &[ $( stringify!( $field ) ),* ]; 819 | deserializer.deserialize_enum( 820 | stringify!($name), 821 | VARIANTS, 822 | EnumVisitor, 823 | ) 824 | } 825 | } 826 | }; 827 | } 828 | 829 | /// Helper macro 830 | #[doc(hidden)] 831 | #[macro_export] 832 | macro_rules! enum_impl { 833 | (FROMS $name: ident: [$($kind: ty),*]) => { 834 | $( 835 | impl From<$name> for $kind { 836 | fn from(value: $name) -> Self { 837 | Self::from(value as u8) 838 | } 839 | } 840 | )* 841 | }; 842 | (VALID_CORE $name: ident: [$($kind: ty),*]) => { 843 | $( 844 | unsafe impl $crate::ValidCheck<$kind> for $name { 845 | const ALWAYS_VALID: bool = >::ALWAYS_VALID; 846 | fn is_valid(value: $kind) -> bool { 847 | Self::is_valid(value as u8) 848 | } 849 | } 850 | )* 851 | }; 852 | (COUNT $head:ident $(,$xs: ident)*) => { 853 | 1 + $crate::enum_impl!(COUNT $($xs),*) 854 | }; 855 | (COUNT) => { 856 | 0 857 | }; 858 | (VALID_BIT_STRUCT $name: ident: [$($kind: ty),*]) => { 859 | $( 860 | unsafe impl $crate::ValidCheck<$kind> for $name { 861 | const ALWAYS_VALID: bool = >::ALWAYS_VALID; 862 | fn is_valid(value: $kind) -> bool { 863 | let inner = value.value(); 864 | Self::is_valid(inner as u8) 865 | } 866 | } 867 | )* 868 | }; 869 | (BITS_FIT_IN $name: ident: [$($kind: ty),+ $(,)?]) => { 870 | $( 871 | impl $crate::BitsFitIn<$kind> for $name { 872 | fn fit(self) -> $kind { 873 | (self as u8).fit() 874 | } 875 | } 876 | )+ 877 | }; 878 | (FROM_IMPLS $name: ident) => { 879 | $crate::enum_impl!(VALID_CORE $name: [u16, u32, u64, u128]); 880 | $crate::enum_impl!(VALID_BIT_STRUCT $name: [$crate::u24, $crate::u40, $crate::u48, $crate::u56]); 881 | $crate::enum_impl!(FROMS $name: [u8, u16, u32, u64, u128, $crate::u24, $crate::u40, $crate::u48, $crate::u56]); 882 | $crate::enum_impl!(BITS_FIT_IN $name: [u8, u16, u32, u64, $crate::u24, $crate::u40, $crate::u48, $crate::u56]); 883 | 884 | impl $crate::FieldStorage for $name { 885 | type StoredType = u8; 886 | 887 | fn inner_raw(self) -> Self::StoredType { 888 | self as Self::StoredType 889 | } 890 | } 891 | 892 | }; 893 | ( 894 | $(#[$meta:meta])* 895 | $enum_vis: vis $name: ident($default: ident) { 896 | $(#[$fst_field_meta:meta])* 897 | $fst_field: ident 898 | $(, 899 | $(#[$field_meta:meta])* 900 | $field: ident 901 | )* $(,)? 902 | } 903 | ) => { 904 | #[repr(u8)] 905 | $(#[$meta])* 906 | #[derive(Copy, Clone, Debug, PartialOrd, PartialEq, Eq)] 907 | $enum_vis enum $name { 908 | $(#[$fst_field_meta])* 909 | $fst_field, 910 | $( 911 | $(#[$field_meta])* 912 | $field 913 | ),* 914 | } 915 | 916 | $crate::enum_serde_impl! { $name { $fst_field $(, $field)* } } 917 | 918 | unsafe impl $crate::BitCount for $name { 919 | const COUNT: usize = $crate::bits($crate::count_idents!(0, [$($field),*])); 920 | } 921 | 922 | impl $name { 923 | const VARIANT_COUNT: usize = $crate::enum_impl!(COUNT $fst_field $(,$field)*); 924 | } 925 | 926 | unsafe impl $crate::ValidCheck for $name { 927 | const ALWAYS_VALID: bool = Self::VARIANT_COUNT.count_ones() == 1; 928 | fn is_valid(value: u8) -> bool { 929 | if (value as usize) < Self::VARIANT_COUNT { 930 | true 931 | } else { 932 | false 933 | } 934 | } 935 | } 936 | 937 | $crate::enum_impl!(FROM_IMPLS $name); 938 | 939 | impl Default for $name { 940 | fn default() -> Self { 941 | Self::$default 942 | } 943 | } 944 | 945 | }; 946 | 947 | 948 | ( 949 | $(#[$meta:meta])* 950 | $enum_vis: vis $name: ident { 951 | $(#[$fst_field_meta:meta])* 952 | $fst_field: ident 953 | $(, 954 | $(#[$field_meta:meta])* 955 | $field: ident 956 | )* $(,)? 957 | } 958 | ) => { 959 | #[repr(u8)] 960 | $(#[$meta])* 961 | #[derive(Copy, Clone, Debug, PartialOrd, PartialEq, Eq)] 962 | $enum_vis enum $name { 963 | $(#[$fst_field_meta])* 964 | $fst_field, 965 | $( 966 | $(#[$field_meta])* 967 | $field 968 | ),* 969 | } 970 | 971 | $crate::enum_serde_impl! { $name { $fst_field $(, $field)* } } 972 | 973 | impl Default for $name { 974 | fn default() -> Self { 975 | Self::$fst_field 976 | } 977 | } 978 | 979 | impl $name { 980 | const VARIANT_COUNT: usize = $crate::enum_impl!(COUNT $fst_field $(,$field)*); 981 | } 982 | 983 | unsafe impl $crate::BitCount for $name { 984 | const COUNT: usize = $crate::bits($crate::count_idents!(0, [$($field),*])); 985 | } 986 | 987 | 988 | unsafe impl $crate::ValidCheck for $name { 989 | const ALWAYS_VALID: bool = Self::VARIANT_COUNT.count_ones() == 1; 990 | 991 | fn is_valid(value: u8) -> bool { 992 | if (value as usize) < Self::VARIANT_COUNT { 993 | true 994 | } else { 995 | false 996 | } 997 | } 998 | } 999 | 1000 | $crate::enum_impl!(FROM_IMPLS $name); 1001 | }; 1002 | } 1003 | 1004 | /// Create enums with trait implementations necessary for use in a `bit_struct` 1005 | /// field. 1006 | /// 1007 | /// Example: 1008 | /// ``` 1009 | /// # use bit_struct::enums; 1010 | /// 1011 | /// enums! { 1012 | /// pub Colors { Red, Green, Blue } 1013 | /// 1014 | /// Shapes { Triangle, Circle, Square } 1015 | /// } 1016 | /// ``` 1017 | /// 1018 | /// By default, this macro produces an impl of [`Default`] in which the first 1019 | /// field listed is made the default. However, you can also specify some other 1020 | /// variant as the default, as follows: 1021 | /// ``` 1022 | /// # use bit_struct::enums; 1023 | /// 1024 | /// enums! { 1025 | /// DefaultsToA { A, B, C } 1026 | /// DefaultsToB (B) { A, B, C } 1027 | /// } 1028 | /// 1029 | /// assert_eq!(DefaultsToA::default(), DefaultsToA::A); 1030 | /// assert_eq!(DefaultsToB::default(), DefaultsToB::B); 1031 | /// ``` 1032 | #[macro_export] 1033 | macro_rules! enums { 1034 | ( 1035 | $( 1036 | $(#[$meta:meta])* 1037 | $enum_vis: vis $name: ident $(($enum_default: ident))? { 1038 | 1039 | $(#[$fst_field_meta:meta])* 1040 | $fst_field: ident 1041 | $(, 1042 | $(#[$field_meta:meta])* 1043 | $field: ident 1044 | )* $(,)? 1045 | } 1046 | )+ 1047 | ) => { 1048 | $( 1049 | $crate::enum_impl!( 1050 | $(#[$meta])* 1051 | $enum_vis $name $(($enum_default))? { 1052 | $(#[$fst_field_meta])* 1053 | $fst_field 1054 | $(, 1055 | $(#[$field_meta])* 1056 | $field 1057 | )* 1058 | } 1059 | ); 1060 | )+ 1061 | } 1062 | } 1063 | 1064 | /// Create a `bit_struct` 1065 | #[macro_export] 1066 | macro_rules! create { 1067 | ( 1068 | $struct_kind: ty { 1069 | $($field: ident: $value: expr),* $(,)? 1070 | } 1071 | ) => { 1072 | { 1073 | let mut res = <$struct_kind>::of_defaults(); 1074 | $( 1075 | res.$field().set($value); 1076 | )* 1077 | res 1078 | } 1079 | }; 1080 | } 1081 | --------------------------------------------------------------------------------