diff --git a/README.md b/README.md
index 8197a26..7d9538c 100644
--- a/README.md
+++ b/README.md
@@ -23,9 +23,63 @@ Add this to your `Cargo.toml`:
bitfield-struct = "0.3"
```
-## Example
+## Basics
+
+Let's begin with a simple example.
+Suppose we want to store multiple data inside a single Byte, as shown below:
+
+
+
+ 7 |
+ 6 |
+ 5 |
+ 4 |
+ 3 |
+ 3 |
+ 1 |
+ 0 |
+
+
+ P |
+ Level |
+ S |
+ Kind |
+
+
+
+This crate generates a nice wrapper type that makes it easy to do this:
-The example below shows the main features of the macro and how to use them.
+```rust
+/// Define your type like this with the bitfield attribute
+#[bitfield(u8)]
+struct MyByte {
+ /// The first field occupies the least significant bits
+ #[bits(4)]
+ kind: usize,
+ /// Booleans are 1 bit large
+ system: bool,
+ /// The bits attribute specifies the bit size of this field
+ #[bits(2)]
+ level: usize,
+ /// The last field spans over the most significant bits
+ present: bool
+}
+// The macro creates three accessor functions for each field:
+// , with_ and set_
+let my_byte = MyByte::new()
+ .with_kind(15)
+ .with_system(false)
+ .with_level(3)
+ .with_present(true);
+
+assert!(my_byte.present());
+```
+
+## Features
+
+Additionally, this crate has a few useful features, which are shown here in more detail.
+
+The example below shows how attributes are carried over and how signed integers, padding, and custom types are handled.
```rust
/// A test bitfield with documentation
diff --git a/src/lib.rs b/src/lib.rs
index 2c756ab..1570cbe 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3,9 +3,72 @@
//! Procedural macro for bitfields that allows specifying bitfields as structs.
//! As this library provides a procedural-macro it has no runtime dependencies and works for `no-std`.
//!
-//! ## Example
+//! - Supports bool flags, raw integers, and every custom type convertible into integers (structs/enums)
+//! - Ideal for driver/OS/embedded development (defining HW registers/structures)
+//! - Generates minimalistic, pure, safe rust functions
+//! - Compile-time checks for type and field sizes
+//! - Rust-analyzer friendly (carries over documentation to accessor functions)
+//! - Exports field offsets and sizes as constants (useful for const asserts)
+//! - Generation of `fmt::Debug`
//!
-//! The example below shows the main features of the macro and how to use them.
+//! ## Basics
+//!
+//! Let's begin with a simple example.
+//! Suppose we want to store multiple data inside a single Byte, as shown below:
+//!
+//!
+//!
+//! 7 |
+//! 6 |
+//! 5 |
+//! 4 |
+//! 3 |
+//! 3 |
+//! 1 |
+//! 0 |
+//!
+//!
+//! P |
+//! Level |
+//! S |
+//! Kind |
+//!
+//!
+//!
+//! This crate is able to generate a nice wrapper type that makes it easy to do this:
+//!
+//! ```
+//! # use bitfield_struct::bitfield;
+//! /// Define your type like this with the bitfield attribute
+//! #[bitfield(u8)]
+//! struct MyByte {
+//! /// The first field occupies the least significant bits
+//! #[bits(4)]
+//! kind: usize,
+//! /// Booleans are 1 bit large
+//! system: bool,
+//! /// The bits attribute specifies the bit size of this field
+//! #[bits(2)]
+//! level: usize,
+//! /// The last field spans over the most significant bits
+//! present: bool
+//! }
+//! // The macro creates three accessor functions for each field:
+//! // , with_ and set_
+//! let my_byte = MyByte::new()
+//! .with_kind(15)
+//! .with_system(false)
+//! .with_level(3)
+//! .with_present(true);
+//!
+//! assert!(my_byte.present());
+//! ```
+//!
+//! ## Features
+//!
+//! Additionally, this crate has a few useful features, which are shown here in more detail.
+//!
+//! The example below shows how attributes are carried over and how signed integers, padding, and custom types are handled.
//!
//! ```
//! # use bitfield_struct::bitfield;
@@ -439,7 +502,7 @@ fn bits(attrs: &[syn::Attribute], ty: &syn::Type) -> syn::Result<(TypeClass, usi
if bits <= size {
Ok((class, bits))
} else {
- Err(syn::Error::new(tokens.span(), "overflowing member type"))
+ Err(syn::Error::new(tokens.span(), "overflowing field type"))
}
} else {
Ok((TypeClass::Other, bits))
diff --git a/tests/test.rs b/tests/test.rs
index 95fbafb..a590979 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -2,71 +2,58 @@ use std::fmt;
use bitfield_struct::bitfield;
-/// A test bitfield with documentation
-#[bitfield(u64)]
-struct MyBitfield {
- /// defaults to 16 bits for u16
- int: u16,
- /// interpreted as 1 bit flag
- flag: bool,
- /// custom bit size
- #[bits(1)]
- tiny: u8,
- /// sign extend for signed integers
- #[bits(13)]
- negative: i16,
- /// supports any type that implements `From` and `Into`
- #[bits(16)]
- custom: CustomEnum,
- /// public field -> public accessor functions
- #[bits(12)]
- pub public: usize,
- /// padding
- #[bits(5)]
- _p: u8,
- /// zero-sized members are ignored
- #[bits(0)]
- _completely_ignored: String,
-}
+#[test]
+fn members() {
+ /// A test bitfield with documentation
+ #[bitfield(u64)]
+ struct MyBitfield {
+ /// defaults to 16 bits for u16
+ int: u16,
+ /// interpreted as 1 bit flag
+ flag: bool,
+ /// custom bit size
+ #[bits(1)]
+ tiny: u8,
+ /// sign extend for signed integers
+ #[bits(13)]
+ negative: i16,
+ /// supports any type that implements `From` and `Into`
+ #[bits(16)]
+ custom: CustomEnum,
+ /// public field -> public accessor functions
+ #[bits(12)]
+ pub public: usize,
+ /// padding
+ #[bits(5)]
+ _p: u8,
+ /// zero-sized members are ignored
+ #[bits(0)]
+ _completely_ignored: String,
+ }
-/// A custom enum
-#[derive(Debug, PartialEq, Eq)]
-#[repr(u64)]
-enum CustomEnum {
- A = 0,
- B = 1,
- C = 2,
-}
-impl From for CustomEnum {
- fn from(value: u64) -> Self {
- match value {
- 0 => Self::A,
- 1 => Self::B,
- _ => Self::C,
- }
+ /// A custom enum
+ #[derive(Debug, PartialEq, Eq)]
+ #[repr(u64)]
+ enum CustomEnum {
+ A = 0,
+ B = 1,
+ C = 2,
}
-}
-impl From for u64 {
- fn from(value: CustomEnum) -> Self {
- value as _
+ impl From for CustomEnum {
+ fn from(value: u64) -> Self {
+ match value {
+ 0 => Self::A,
+ 1 => Self::B,
+ _ => Self::C,
+ }
+ }
}
-}
-
-/// We have a custom debug implementation -> opt out
-#[bitfield(u64, debug = false)]
-#[derive(PartialEq, Eq, Default)]
-struct Full {
- data: u64,
-}
-
-impl fmt::Debug for Full {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "0x{:x}", self.data())
+ impl From for u64 {
+ fn from(value: CustomEnum) -> Self {
+ value as _
+ }
}
-}
-#[test]
-fn members() {
let mut val = MyBitfield::new()
.with_int(3 << 15)
.with_flag(true)
@@ -100,8 +87,15 @@ fn members() {
#[test]
fn attrs() {
+ /// We have a custom debug implementation -> opt out
+ #[bitfield(u64)]
+ #[derive(PartialEq, Eq, Default)]
+ struct Full {
+ data: u64,
+ }
+
let full = Full::default();
- assert_eq!(full, Full::new());
+ assert_eq!(full.0, Full::new().0);
let full = Full::new().with_data(u64::MAX);
assert_eq!(full.data(), u64::MAX);
@@ -110,6 +104,18 @@ fn attrs() {
#[test]
fn debug() {
- let full = Full::default();
+ /// We have a custom debug implementation -> opt out
+ #[bitfield(u64, debug = false)]
+ struct Full {
+ data: u64,
+ }
+
+ impl fmt::Debug for Full {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "0x{:x}", self.data())
+ }
+ }
+
+ let full = Full::new().with_data(123);
println!("{full:?}");
}