bitstructs/
lib.rs

1#![cfg_attr(feature = "no_std", no_std)]
2//! `bitstructs` is a library for defining type-safe bitfield structures
3//! that can be used in both `std` and `no_std` environments.
4//!
5//! The library provides three macros, [`bitstruct_cow`], [`bitstruct_owned`],
6//! and [`bitstruct_small`], for generating `BitStruct`. It also includes
7//! the [`bitstruct_field_enum`] macro for safely generating enum types
8//! for fields within `BitStruct`. Only [`bitstruct_cow`] is not supported
9//! in `no_std` environments because it relies on [`std::borrow::Cow`].
10//!
11//!
12//! `bitstructs`是一个可同时用于std和no_std 环境,定义类型安全的位域结构体的库。
13//!
14//! 该库提供了[`bitstruct_cow`]、[`bitstruct_owned`]、[`bitstruct_small`]三个宏,
15//! 用于生成`BitStruct`。以及[`bitstruct_field_enum`]宏,用于安全的生成`BitStruct`中字段枚举类型。
16//! 其中只有[`bitstruct_cow`] 因为需要使用[`std::borrow::Cow`] ,所以不支持 no_std 环境。
17//!
18//! ## Defining `BitStruct`
19//!
20//! The usage of the three macros, [bitstruct_cow], [bitstruct_owned],
21//! and [bitstruct_small], is similar.
22//!
23//! The syntax is similar to Rust's struct definition, except that
24//! a number is used after the field name to indicate the bit width
25//! instead of the type. You can optionally use `=>` to specify
26//! the corresponding enum type for the field. The field's enum type
27//! can be declared inline or referenced from an external definition.
28//!
29//!
30//! [`bitstruct_cow`]、[`bitstruct_owned`]、[`bitstruct_small`]三个宏的使用方法类似。
31//!
32//! 语法类似rust的结构体定义,只是在字段名后使用数字表示位宽而非类型,
33//! 然后可以选择的使用`=>`设置字段的对应的枚举类型。字段枚举类型可以
34//! 使用内联枚举声明,也可以使用外部定义的枚举类型。
35//!
36//! ```
37//! use bitstructs::{bitstruct_owned};
38//!
39//! bitstruct_owned! {
40//!     #[derive(Clone, Debug, PartialEq)]
41//!     pub struct Foo {
42//!         a: 1,
43//!         b: 2,
44//!         c: 2 =>
45//!         pub enum C {
46//!             C0 = 0,
47//!             C1 = 1,
48//!         },
49//!     }
50//! }
51//! let mut value = Foo::new();
52//! assert_eq!(value.as_bytes(), vec![0b0000_0000]);
53//! value.set_a(true);
54//! unsafe { value.set_b(1) };
55//! value.set_c(C::C1);
56//! assert_eq!(value.as_bytes(), vec![0b0000_1011]);
57//! ```
58//!
59//! By default, the library uses LSB0 and little-endian mode.
60//! To use MSB0 and big-endian mode, add `#[bitstruct_repr(MSB0)]` to the struct.
61//!
62//! 默认情况下,采取的是LSB0和小端模式。如果要使用MSB0和大端模式,
63//! 可以在结构体上添加中添加`#[bitstruct_repr(MSB0)]`。
64//!
65//! ```
66//! use bitstructs::{bitstruct_owned};
67//!
68//! /// MSB0 and big-endian mode
69//! /// MSB0和大端模式
70//! bitstruct_owned! {
71//!     #[derive(Clone, Debug, PartialEq)]
72//!     #[bitstruct_repr(MSB0)]
73//!     pub struct Foo {
74//!         a: 1,
75//!         b: 2,
76//!         c: 2 =>
77//!         pub enum C {
78//!             C0 = 0,
79//!             C1 = 1,
80//!         },
81//!     }
82//! }
83//! let mut value = Foo::new();
84//! assert_eq!(value.as_bytes(), vec![0b0000_0000]);
85//! value.set_a(true);
86//! unsafe { value.set_b(1) };
87//! value.set_c(C::C1);
88//! assert_eq!(value.as_bytes(), vec![0b1010_1000]);
89//! ```
90//!
91//! The [`bitstruct_owned`] macro generates the following methods:
92//! - `fn new() -> Self`: Creates a new `BitStruct`.
93//! - `fn bytes_len() -> usize`: Gets the number of bytes occupied by the `BitStruct`.
94//! - `fn from_bytes(bytes: &[u8]) -> Result<Self, BitStructError>`: Creates a `BitStruct` from a byte array.
95//! - `fn as_bytes(&self) -> &[u8]`: Gets an immutable reference to the byte array of the `BitStruct`.
96//! - `fn as_bytes_mut(&mut self) -> &mut [u8]`: Gets a mutable reference to the byte array of the `BitStruct`.
97//! - Methods for reading and setting each field. For fields without a specified enum type, the type will be chosen from `bool`, `u8`, `u16`, `u32`, or `u128`. Fields exceeding 128 bits will cause a compilation failure.
98//!     For example, `fn b(&self) -> u8` and `unsafe fn set_b(&mut self, value: u8)`,
99//!         `fn c(&self) -> C` and `fn set_c(&mut self, value: C)`.
100//!
101//! The usage of [`bitstruct_cow`] is the same as [`bitstruct_owned`],
102//! but the generated `BitStruct` uses `Cow` internally. Additionally,
103//! `as_bytes` and `as_bytes_mut` are replaced with `to_bytes` and `to_bytes_mut`.
104//!
105//! The usage of [`bitstruct_small`] is similar to [`bitstruct_owned`],
106//! but it restricts the size of `BitStruct` to a maximum of 128 bits.
107//! It does not support `#[bitstruct_repr(MSB0)]` but allows `#[bitstruct_repr(u8)]`
108//! to explicitly specify the internal storage type of `BitStruct`.
109//!
110//!
111//! [`bitstruct_owned`]宏会生成以下方法:
112//! - `fn new() -> Self`:创建一个新的`BitStruct`。
113//! - `fn bytes_len() -> usize`:获取`BitStruct`占用的字节数。
114//! - `fn from_bytes(bytes: &[u8]) -> Result<Self, BitStructError>`:从字节数组中创建`BitStruct`。
115//! - `fn as_bytes(&self) -> &[u8]`:获取`BitStruct`的字节数组引用。
116//! - `fn as_bytes_mut(&mut self) -> &mut [u8]`:获取`BitStruct`的字节数组可变引用。
117//! - 各个字段的读取和设置方法,对于没有指定枚举类型的字段,类型将会使用`bool`,`u8`,`u16`,`u32`,`u128`中选择。超过128位,将会编译失败。
118//!     例如`fn b(&self) -> u8`和`unsafe fn set_b(&mut self, value: u8)`,
119//!         `fn c(&self) -> C`和`fn set_c(&mut self, value: C)`。
120//!
121//! [`bitstruct_cow`]的使用和[`bitstruct_owned`]相同,只是生成的`BitStruct`内部是`Cow`类型,
122//! 以及将`as_bytes`,`as_bytes_mut`换成了`to_bytes`,`to_bytes_mut`。
123//!
124//! [`bitstruct_small`]的使用和[`bitstruct_owned`]类似。但是限制了`BitStruct`的大小,最大为128位。
125//! 以及不支持使用`#[bitstruct_repr(MSB0)]`,但是支持`#[bitstruct_repr(u8)]`去显示指定`BitStruct`内部的实际存储类型。
126//!
127//! ```
128//! use bitstructs::{bitstruct_small};
129//!
130//! /// Specifying the storage type as u32
131//! /// 指定存储类型为u32
132//! bitstruct_small! {
133//!     #[derive(Clone, Debug, PartialEq)]
134//!     #[bitstruct_repr(u32)]
135//!     pub struct Foo {
136//!         a: 1,
137//!         b: 2,
138//!         reserved: 2,
139//!         c: 2 =>
140//!         #[derive(Debug, PartialEq, Eq)]
141//!         pub enum C {
142//!             C0 = 0,
143//!             C1 = 1,
144//!         },
145//!     }
146//! }
147//! let value: u32 = 0b0100_10_1;
148//! let value = Foo::from_value(value);
149//! assert_eq!(value.a(), true);
150//! assert_eq!(value.b(), 2);
151//! assert_eq!(value.c(), C::C1);
152//! ```
153//!
154//! ## Defining Enum Types
155//!
156//! In addition to defining enum types within the `bitstruct_owned`, `bitstruct_cow`,
157//! and `bitstruct_small` macros as shown in the example above, enum types can also
158//! be defined externally. Unlike inline enums, externally defined enum types can be reused. Here is a simple example:
159//!
160//! 除了像上面例子那样,在`bitstruct_owned`、`bitstruct_cow`、`bitstruct_small`宏中定义枚举类型,还可以在外部定义枚举类型。
161//! 在外部定义的枚举类型,不同于内联枚举,可以重复使用。下面是一个简单的例子:
162//!
163//! ```
164//! use bitstructs::{bitstruct_field_enum, bitstruct_owned};
165//!
166//! /// This is an enum type suitable for 2 bits
167//! /// 这是一个适用于 2 bit 的枚举类型
168//! #[bitstruct_field_enum(2)]
169//! pub enum TwoBitEnum {
170//!     Zero = 0,
171//!     One = 1,
172//!     Two = 2,
173//!     Three = 3,
174//! }
175//! bitstruct_owned! {
176//!     pub struct Foo {
177//!         a: 4,
178//!         b: 2 => TwoBitEnum,
179//!         c: 2 => TwoBitEnum,
180//!     }
181//! }
182//! ```
183//!
184//! If the variants in the enum type do not cover all possible values,
185//! variants with the prefix `__Reserved` will be automatically added.
186//! This also applies to inline enum types.
187//!
188//!
189//! 如果枚举类型中的变体(variants)没有覆盖所有可能的取值,
190//! 会自动添加前缀为 `__Reserved` 的变体。这同样适用于内联枚举类型。
191//!
192//! ```
193//! use bitstructs::{bitstruct_field_enum,bitstruct_owned};
194//! #[bitstruct_field_enum(2)]
195//! pub enum TwoBitEnum {
196//!    Zero = 0,
197//!    Two = 2,
198//! }
199//! bitstruct_owned! {
200//!     pub struct Foo {
201//!         a: 4,
202//!         b: 2 =>
203//!         enum B {
204//!             Foo = 2,
205//!             Bar = 3,
206//!         },
207//!     }
208//! }
209//! ```
210//!
211//! The code above is equivalent to:
212//!
213//! ```
214//! use bitstructs::{bitstruct_field_enum,bitstruct_owned};
215//! #[bitstruct_field_enum(2)]
216//! pub enum TwoBitEnum {
217//!     Zero = 0,
218//!     Two = 2,
219//!     __Reserved1 = 1,
220//!     __Reserved3 = 3,
221//! }
222//! bitstruct_owned! {
223//!     pub struct Foo {
224//!         a: 4,
225//!         b: 2 =>
226//!         enum B {
227//!             Foo = 2,
228//!             Bar = 3,
229//!             __Reserved0 = 0,
230//!             __Reserved1 = 1,
231//!         },
232//!     }
233//! }
234//! ```
235//!
236//! ## Confusing Error Messages
237//!
238//! If the bit width of the enum type does not match the bit width of the field
239//! in `BitStruct`, compilation will fail. However, since the current check
240//! for non-inline enum types uses `const` to trigger a compilation error through overflow,
241//! the error message may not be very friendly when the bit widths do not match.
242//!
243//! 如果枚举类型的位宽与 `BitStruct` 中字段的位宽不匹配,编译将会失败。
244//! 然而,由于当前对非内联枚举类型的检查是通过使用 `const` 来触发编译错误(利用溢出),
245//! 因此当位宽不匹配时,错误信息不够友好。
246//!
247//! ```compile_fail
248//! use bitstructs::{bitstruct_field_enum,bitstruct_owned};
249//! #[bitstruct_field_enum(2)]
250//! pub enum TwoBitEnum {
251//!    Zero = 0,
252//!    One = 1,
253//!    Two = 2,
254//!    Three = 3,
255//! }
256//! bitstruct_owned! {
257//!     pub struct Foo {
258//!         a: 4,
259//!         b: 3 => TwoBitEnum,
260//!     }
261//! }
262//! ```
263//!
264//! The code above will fail to compile with an error message similar to:
265//!
266//! ```text
267//! error[E0080]: evaluation of constant value failed
268//!   --> bitstructs/src/main.rs:9:1
269//!    |
270//! 9  | / bitstruct_owned! {
271//! 10 | |     pub struct Foo {
272//! 11 | |         a: 4,
273//! 12 | |         b: 3 => TwoBitEnum,
274//! 13 | |     }
275//! 14 | | }
276//!    | |_^ attempt to compute `0_u32 - u32::MAX`, which would overflow
277//! ```
278//!
279//! Declaring inline enum types is checked during macro expansion,
280//! which results in more friendly error messages.
281//!
282//! ```compile_fail
283//! use bitstructs::{bitstruct_small};
284//! bitstruct_small! {
285//!     pub struct Foo {
286//!         a: 4,
287//!         b: 2 =>
288//!         enum B {
289//!            Zero = 0,
290//!            One = 1,
291//!            Two = 2,
292//!            Three = 3,
293//!            Four = 4
294//!        },
295//!     }
296//! }
297//! ```
298//! The code above will fail to compile with an error message similar to:
299//!
300//! ```text
301//! error: enum type variant count must be less than or equal to 2^2
302//!  --> bitstructs/src/main.rs:5:22
303//!   |
304//! 6 |         enum B {
305//!   |              ^
306//! ```
307//!
308macro_rules! with_doc {
309    ($($tokens:tt)*) => {
310        /// A trait that must be implemented for non-inline field enum types. 非内联的字段枚举类型必须实现的trait。
311        ///
312        /// It is recommended to use the [`bitstruct_field_enum`] macro to generate non-inline field enum types instead of implementing them manually.
313        ///
314        /// 推荐使用[`bitstruct_field_enum`]宏来生成非内联的字段枚举类型。而不是手动实现。
315        ///
316        /// ```
317        /// use bitstructs::{bitstruct_field_enum};
318        /// #[bitstruct_field_enum(2)]
319        /// pub enum TwoBitEnum {
320        ///     Zero = 0,
321        ///     One = 1,
322        ///     Two = 2,
323        ///     Three = 3,
324        /// }
325        /// ``````
326        ///
327        /// # Safety
328        ///
329        /// 1. Must be able to handle all values from `0` to `2.pow(BIT_WIDTH) - 1`.
330        /// 2. Must implement both [`BitstructToValue`] and [`BitstructFromValue`].
331        /// 3. The `StoreType` must be the smallest unsigned integer type that can contain all possible values, which can be one of [`u8`], [`u16`], [`u32`], [`u64`], or [`u128`].
332        /// 4. The operations of [`BitstructFromValue::from_value`] and [`BitstructToValue::to_value`] must be inverse of each other.
333        /// 5. The `BIT_WIDTH` of [`BitstructFromValue`] and [`BitstructToValue`] must be the same.
334        ///
335        /// 1. 必须能处理 0 到 `2.pow(BIT_WIDTH) - 1` 的所有取值。
336        /// 2. 必须同时实现[`BitstructToValue`]和[`BitstructFromValue`]。
337        /// 3. `StoreType`必须是能包含所有可能取值范围的最小的无符号整数类型,可使用[`u8`],[`u16`],[`u32`],[`u64`],[`u128`]。
338        /// 4. [`BitstructFromValue::from_value`]和[`BitstructToValue::to_value`]必须是互为逆操作。
339        /// 5. [`BitstructFromValue`]和[`BitstructToValue`]的`BIT_WIDTH`必须相同。
340        ///
341        $($tokens)*
342    };
343}
344
345with_doc! {
346    pub unsafe trait BitstructFromValue {
347        const BIT_WIDTH: u32;
348        type StoreType;
349        unsafe fn from_value(value: Self::StoreType) -> Self;
350    }
351}
352
353with_doc! {
354    pub unsafe trait BitstructToValue {
355        const BIT_WIDTH: u32;
356        type StoreType;
357        unsafe fn to_value(self) -> Self::StoreType;
358    }
359}
360
361#[cfg(not(feature = "no_std"))]
362pub use bitstructs_macro::bitstruct_cow;
363pub use bitstructs_macro::bitstruct_field_enum;
364pub use bitstructs_macro::bitstruct_owned;
365pub use bitstructs_macro::bitstruct_repr;
366pub use bitstructs_macro::bitstruct_small;
367
368/// ```compile_fail
369/// use bitstructs::{bitstruct_field_enum,bitstruct_owned};
370/// #[bitstruct_field_enum(2)]
371/// pub enum TwoBitEnum {
372///    Zero = 0,
373///    One = 1,
374///    Two = 2,
375///    Three = 3,
376/// }
377/// bitstruct_owned! {
378///     pub struct Foo {
379///         a: 4,
380///         b: 3 => TwoBitEnum,
381///     }
382/// }
383/// ```
384///
385/// ```compile_fail
386/// use bitstructs::{bitstruct_field_enum,bitstruct_cow};
387/// #[bitstruct_field_enum(2)]
388/// pub enum TwoBitEnum {
389///    Zero = 0,
390///    One = 1,
391///    Two = 2,
392///    Three = 3,
393/// }
394/// bitstruct_cow! {
395///     pub struct Foo {
396///         a: 4,
397///         b: 3 => TwoBitEnum,
398///     }
399/// }
400/// ```
401///
402/// ```compile_fail
403/// use bitstructs::{bitstruct_field_enum,bitstruct_small};
404/// #[bitstruct_field_enum(2)]
405/// pub enum TwoBitEnum {
406///    Zero = 0,
407///    One = 1,
408///    Two = 2,
409///    Three = 3,
410/// }
411/// bitstruct_small! {
412///     pub struct Foo {
413///         a: 4,
414///         b: 3 => TwoBitEnum,
415///     }
416/// }
417/// ```
418#[doc(hidden)]
419#[allow(dead_code)]
420fn test_should_compile_fail() {
421    unreachable!("This function should not be called.");
422}