Crate bitstructs

Source
Expand description

bitstructs is a library for defining type-safe bitfield structures that can be used in both std and no_std environments.

The library provides three macros, bitstruct_cow, bitstruct_owned, and bitstruct_small, for generating BitStruct. It also includes the bitstruct_field_enum macro for safely generating enum types for fields within BitStruct. Only bitstruct_cow is not supported in no_std environments because it relies on std::borrow::Cow.

bitstructs是一个可同时用于std和no_std 环境,定义类型安全的位域结构体的库。

该库提供了bitstruct_cowbitstruct_ownedbitstruct_small三个宏, 用于生成BitStruct。以及bitstruct_field_enum宏,用于安全的生成BitStruct中字段枚举类型。 其中只有bitstruct_cow 因为需要使用std::borrow::Cow ,所以不支持 no_std 环境。

§Defining BitStruct

The usage of the three macros, bitstruct_cow, bitstruct_owned, and bitstruct_small, is similar.

The syntax is similar to Rust’s struct definition, except that a number is used after the field name to indicate the bit width instead of the type. You can optionally use => to specify the corresponding enum type or supported primitive type, such as bool, u8, u16, u32, u64, and u128, for the field. If not specified, the smallest primitive type that can contain the field will be chosen. The field’s enum type can be declared inline or referenced from an external definition.

Note: => specifies the type used for reading and writing the field, and does not affect the storage type of the field.

bitstruct_cowbitstruct_ownedbitstruct_small三个宏的使用方法类似。

语法类似rust的结构体定义,只是在字段名后使用数字表示位宽而非类型, 然后可以选择的使用=>设置字段的对应的枚举类型或支持的基本类型,如bool,u8,u16,u32,u64,u128, 如果没有指定,默认选择可容纳字段的最小基本类型。字段枚举类型可以使用内联枚举声明, 也可以使用外部定义的枚举类型。

注意:=>指定的类型只是用于字段的读取和写入的类型,不会影响字段的存储类型。

use bitstructs::{bitstruct_owned};

bitstruct_owned! {
    #[derive(Clone, Debug, PartialEq)]
    pub struct Foo {
        a: 1 => bool,
        b: 2, // equivalent to `b: 2 => u8`
        c: 2 =>
        pub enum C {
            C0 = 0,
            C1 = 1,
        },
    }
}
let mut value = Foo::new();
assert_eq!(value.as_bytes(), vec![0b0000_0000]);
value.set_a(true);
unsafe { value.set_b(1) };
value.set_c(C::C1);
assert_eq!(value.as_bytes(), vec![0b0000_1011]);

By default, the library uses LSB0 and little-endian mode. To use MSB0 and big-endian mode, add #[bitstruct_repr(MSB0)] to the struct.

默认情况下,采取的是LSB0和小端模式。如果要使用MSB0和大端模式, 可以在结构体上添加中添加#[bitstruct_repr(MSB0)]

use bitstructs::{bitstruct_owned};

/// MSB0 and big-endian mode
/// MSB0和大端模式
bitstruct_owned! {
    #[derive(Clone, Debug, PartialEq)]
    #[bitstruct_repr(MSB0)]
    pub struct Foo {
        a: 1 => bool,
        b: 2, // equivalent to `b: 2 => u8`
        c: 2 =>
        pub enum C {
            C0 = 0,
            C1 = 1,
        },
    }
}
let mut value = Foo::new();
assert_eq!(value.as_bytes(), vec![0b0000_0000]);
value.set_a(true);
unsafe { value.set_b(1) };
value.set_c(C::C1);
assert_eq!(value.as_bytes(), vec![0b1010_1000]);

The usage of bitstruct_cow is the same as bitstruct_owned, but the generated BitStruct uses Cow internally. Additionally, as_bytes and as_bytes_mut are replaced with to_bytes and to_bytes_mut.

The usage of bitstruct_small is similar to bitstruct_owned, but it restricts the size of BitStruct to a maximum of 128 bits. It does not support #[bitstruct_repr(MSB0)] but allows #[bitstruct_repr(u8)] to explicitly specify the internal storage type of BitStruct.

The methods generated by bitstruct_owned, bitstruct_cow, and bitstruct_small can refer to the examples in examples.

bitstruct_cow的使用和bitstruct_owned相同,只是生成的BitStruct内部是Cow类型, 以及将as_bytes,as_bytes_mut换成了to_bytesto_bytes_mut

bitstruct_small的使用和bitstruct_owned类似。但是限制了BitStruct的大小,最大为128位。 以及不支持使用#[bitstruct_repr(MSB0)],但是支持#[bitstruct_repr(u8)]去显示指定BitStruct内部的实际存储类型。

bitstruct_ownedbitstruct_cowbitstruct_small生成的方法可参考examples中的例子。

use bitstructs::{bitstruct_small};

/// Specifying the storage type as u32
/// 指定存储类型为u32
bitstruct_small! {
    #[derive(Clone, Debug, PartialEq)]
    #[bitstruct_repr(u32)]
    pub struct Foo {
        a: 1 => bool,
        b: 2 => u32,
        reserved: 2,
        c: 2 =>
        #[derive(Debug, PartialEq, Eq)]
        pub enum C {
            C0 = 0,
            C1 = 1,
        },
    }
}
let value: u32 = 0b0100_10_1;
let value = Foo::from_value(value);
assert_eq!(value.a(), true);
assert_eq!(value.b(), 2u32);
assert_eq!(value.c(), C::C1);

§Defining Enum Types

In addition to defining enum types within the bitstruct_owned, bitstruct_cow, and bitstruct_small macros as shown in the example above, enum types can also be defined externally. Unlike inline enums, externally defined enum types can be reused. Here is a simple example:

除了像上面例子那样,在bitstruct_ownedbitstruct_cowbitstruct_small宏中定义枚举类型,还可以在外部定义枚举类型。 在外部定义的枚举类型,不同于内联枚举,可以重复使用。下面是一个简单的例子:

use bitstructs::{bitstruct_field_enum, bitstruct_owned};

/// This is an enum type suitable for 2 bits
/// 这是一个适用于 2 bit 的枚举类型
#[bitstruct_field_enum(2)]
#[derive(Debug)]
pub enum TwoBitEnum {
    Zero = 0,
    One = 1,
    Two = 2,
    Three = 3,
}
bitstruct_owned! {
    pub struct Foo {
        a: 4,
        b: 2 => TwoBitEnum,
        c: 2 => TwoBitEnum,
    }
}

If the variants in the enum type do not cover all possible values, variants with the prefix __Reserved will be automatically added. This also applies to inline enum types.

Note: #[bitstruct_field_enum(2)] should be placed above #[derive(Debug)], otherwise Debug will not recognize the automatically completed variants.

如果枚举类型中的变体(variants)没有覆盖所有可能的取值, 会自动添加前缀为 __Reserved 的变体。这同样适用于内联枚举类型。

注意#[#[bitstruct_field_enum(2)]应该在#[derive(Debug)]上方,否则Debug不会识别到自动补全的变体。

use bitstructs::{bitstruct_field_enum,bitstruct_owned};
#[bitstruct_field_enum(2)]
#[derive(Debug)]
pub enum TwoBitEnum {
   Zero = 0,
   Two = 2,
}
bitstruct_owned! {
    pub struct Foo {
        a: 4,
        b: 2 =>
        enum B {
            Foo = 2,
            Bar = 3,
        },
    }
}

The code above is equivalent to:

use bitstructs::{bitstruct_field_enum,bitstruct_owned};
#[bitstruct_field_enum(2)]
#[derive(Debug)]
pub enum TwoBitEnum {
    Zero = 0,
    Two = 2,
    __Reserved1 = 1,
    __Reserved3 = 3,
}
bitstruct_owned! {
    pub struct Foo {
        a: 4,
        b: 2 =>
        enum B {
            Foo = 2,
            Bar = 3,
            __Reserved0 = 0,
            __Reserved1 = 1,
        },
    }
}

§Confusing Error Messages

If the bit width of the enum type does not match the bit width of the field in BitStruct, compilation will fail. However, since the current check for non-inline enum types uses const to trigger a compilation error through overflow, the error message may not be very friendly when the bit widths do not match.

如果枚举类型的位宽与 BitStruct 中字段的位宽不匹配,编译将会失败。 然而,由于当前对非内联枚举类型的检查是通过使用 const 来触发编译错误(利用溢出), 因此当位宽不匹配时,错误信息不够友好。

use bitstructs::{bitstruct_field_enum,bitstruct_owned};
#[bitstruct_field_enum(2)]
pub enum TwoBitEnum {
   Zero = 0,
   One = 1,
   Two = 2,
   Three = 3,
}
bitstruct_owned! {
    pub struct Foo {
        a: 4,
        b: 3 => TwoBitEnum,
    }
}

The code above will fail to compile with an error message similar to:

error[E0080]: evaluation of constant value failed
  --> bitstructs/src/main.rs:9:1
   |
9  | / bitstruct_owned! {
10 | |     pub struct Foo {
11 | |         a: 4,
12 | |         b: 3 => TwoBitEnum,
13 | |     }
14 | | }
   | |_^ attempt to compute `0_u32 - u32::MAX`, which would overflow

Declaring inline enum types is checked during macro expansion, which results in more friendly error messages.

use bitstructs::{bitstruct_small};
bitstruct_small! {
    pub struct Foo {
        a: 4,
        b: 2 =>
        enum B {
           Zero = 0,
           One = 1,
           Two = 2,
           Three = 3,
           Four = 4
       },
    }
}

The code above will fail to compile with an error message similar to:

error: enum type variant count must be less than or equal to 2^2
 --> bitstructs/src/main.rs:5:22
  |
6 |         enum B {
  |              ^

Modules§

examples
Examples of using bitstructs in macro expansion, used to better demonstrate the methods generated by the macro. 使用宏定义的bitstructs例子,用于更好的展示宏的展开后产生的方法。

Macros§

bitstruct_cow
Use Cow to implement BitStruct. 使用写时复制的BitStruct实现。
bitstruct_owned
Copy the byte data directly, the BitStruct implementation with ownership. 直接复制字节数据,拥有所有权的BitStruct实现。
bitstruct_small
Suitable for small data structure BitStruct implementation. 适用于小型数据结构的BitStruct实现。

Traits§

BitstructFromValue
A trait that must be implemented for non-inline field enum types. 非内联的字段枚举类型必须实现的trait。
BitstructToValue
A trait that must be implemented for non-inline field enum types. 非内联的字段枚举类型必须实现的trait。

Attribute Macros§

bitstruct_field_enum
Used to declare the enumeration type of the field. 用于声明字段的枚举类型。
bitstruct_repr
Used to declare the representation of BitStruct’s store_type or bit_numbering. 用于描述BitStruct的store_type或bit_numbering.