비트 필드를 스트러크로 지정할 수있는 비트 필드의 절차 매크로. 이 라이브러리는 절차 적 매크로를 제공하므로 런타임 종속성이 없으며 no-std 환경에서 작동합니다.
Default 생성, fmt::Debug 또는 defmt::Format 특성 이것을 Cargo.toml 에 추가하십시오.
[ dependencies ]
bitfield-struct = " 0.10 " 간단한 예로 시작합시다. 아래와 같이 여러 데이터를 단일 바이트 내에 저장한다고 가정합니다.
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| 피 | 수준 | 에스 | 친절한 | ||||
이 상자는이 작업을 쉽게 할 수있는 멋진 래퍼 유형을 생성합니다.
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:
// <name>, with_<name> and set_<name>
let my_byte = MyByte :: new ( )
. with_kind ( 15 )
. with_system ( false )
. with_level ( 3 )
. with_present ( true ) ;
assert ! ( my_byte . present ( ) ) ; 또한이 상자에는 몇 가지 유용한 기능이 있으며 여기에는 자세히 표시됩니다.
아래의 예는 속성이 어떻게 운반되는지와 서명 정수, 패딩 및 사용자 정의 유형을 처리하는 방법을 보여줍니다.
use bitfield_struct :: bitfield ;
/// A test bitfield with documentation
# [ bitfield ( u64 ) ]
# [ derive ( PartialEq , Eq ) ] // <- Attributes after `bitfield` are carried over
struct MyBitfield {
/// Defaults to 16 bits for u16
int : u16 ,
/// Interpreted as 1 bit flag, with a custom default value
# [ bits ( default = true ) ]
flag : bool ,
/// Custom bit size
# [ bits ( 1 ) ]
tiny : u8 ,
/// Sign extend for signed integers
# [ bits ( 13 ) ]
negative : i16 ,
/// Supports any type with `into_bits`/`from_bits` functions
# [ bits ( 16 ) ]
custom : CustomEnum ,
/// Public field -> public accessor functions
# [ bits ( 10 ) ]
pub public : usize ,
/// Also supports read-only fields
# [ bits ( 1 , access = RO ) ]
read_only : bool ,
/// And write-only fields
# [ bits ( 1 , access = WO ) ]
write_only : bool ,
/// Padding
# [ bits ( 5 ) ]
__ : u8 ,
}
/// A custom enum
# [ derive ( Debug , PartialEq , Eq ) ]
# [ repr ( u16 ) ]
enum CustomEnum {
A = 0 ,
B = 1 ,
C = 2 ,
}
impl CustomEnum {
// This has to be a const fn
const fn into_bits ( self ) -> u16 {
self as _
}
const fn from_bits ( value : u16 ) -> Self {
match value {
0 => Self :: A ,
1 => Self :: B ,
_ => Self :: C ,
}
}
}
// Usage:
let mut val = MyBitfield :: new ( )
. with_int ( 3 << 15 )
. with_tiny ( 1 )
. with_negative ( - 3 )
. with_custom ( CustomEnum :: B )
. with_public ( 2 )
// .with_read_only(true) <- Would not compile
. with_write_only ( false ) ;
println ! ( "{val:?}" ) ;
let raw : u64 = val . into ( ) ;
println ! ( "{raw:b}" ) ;
assert_eq ! ( val . int ( ) , 3 << 15 ) ;
assert_eq ! ( val . flag ( ) , true ) ;
assert_eq ! ( val . negative ( ) , - 3 ) ;
assert_eq ! ( val . tiny ( ) , 1 ) ;
assert_eq ! ( val . custom ( ) , CustomEnum :: B ) ;
assert_eq ! ( val . public ( ) , 2 ) ;
assert_eq ! ( val . read_only ( ) , false ) ;
// const members
assert_eq ! ( MyBitfield :: FLAG_BITS , 1 ) ;
assert_eq ! ( MyBitfield :: FLAG_OFFSET , 16 ) ;
val . set_negative ( 1 ) ;
assert_eq ! ( val . negative ( ) , 1 ) ;매크로는 각 필드에 대해 세 가지 액세서 기능을 생성합니다. 각 액세서는 또한 해당 분야의 문서를 물려받습니다.
int 의 서명은 다음과 같습니다.
// generated struct
struct MyBitfield ( u64 ) ;
impl MyBitfield {
const fn new ( ) -> Self { Self ( 0 ) }
const INT_BITS : usize = 16 ;
const INT_OFFSET : usize = 0 ;
const fn int ( & self ) -> u16 { todo ! ( ) }
const fn with_int ( self , value : u16 ) -> Self { todo ! ( ) }
const fn with_int_checked ( self , value : u16 ) -> Result < Self , ( ) > { todo ! ( ) }
const fn set_int ( & mut self , value : u16 ) { todo ! ( ) }
const fn set_int_checked ( & mut self , value : u16 ) -> Result < ( ) , ( ) > { todo ! ( ) }
// other field ...
}
// Also generates From<u64>, Into<u64>, Default, and Debug implementations...힌트 : Rust-Analyzer "확장 매크로 재귀 적으로"조치를 사용하여 생성 된 코드를 볼 수 있습니다.
매크로는 기본 비트 필드 유형으로 변환 가능한 모든 유형을 지원합니다. 이것은 다음 예제 또는 다른 구조물에서와 같이 열거 될 수 있습니다.
변환 및 기본값은 다음 #[bits] 매개 변수로 지정할 수 있습니다.
from : 원시 비트에서 사용자 정의 유형으로 변환하는 기능, 기본값 <ty>::from_bitsinto : 사용자 정의 유형에서 원시 비트로 변환하는 기능, 기본값 <ty>::into_bitsdefault : Custom Expression, <ty>::from_bits(0) 호출 기본값 use bitfield_struct :: bitfield ;
# [ bitfield ( u16 ) ]
# [ derive ( PartialEq , Eq ) ]
struct Bits {
/// Supports any convertible type
# [ bits ( 8 , default = CustomEnum :: B , from = CustomEnum :: my_from_bits ) ]
custom : CustomEnum ,
/// And nested bitfields
# [ bits ( 8 ) ]
nested : Nested ,
}
# [ derive ( Debug , PartialEq , Eq ) ]
# [ repr ( u8 ) ]
enum CustomEnum {
A = 0 ,
B = 1 ,
C = 2 ,
}
impl CustomEnum {
// This has to be a const fn
const fn into_bits ( self ) -> u8 {
self as _
}
const fn my_from_bits ( value : u8 ) -> Self {
match value {
0 => Self :: A ,
1 => Self :: B ,
_ => Self :: C ,
}
}
}
/// Bitfields implement the conversion functions automatically
# [ bitfield ( u8 ) ]
struct Nested {
# [ bits ( 4 ) ]
lo : u8 ,
# [ bits ( 4 ) ]
hi : u8 ,
} 선택적 order 매크로 인수는 비트의 레이아웃을 결정하고 기본값은 LSB (최소 유의미한 비트)입니다.
use bitfield_struct :: bitfield ;
# [ bitfield ( u8 , order = Lsb ) ]
struct MyLsbByte {
/// The first field occupies the *least* significant bits
# [ bits ( 4 ) ]
kind : usize ,
system : bool ,
# [ bits ( 2 ) ]
level : usize ,
present : bool
}
let my_byte_lsb = MyLsbByte :: new ( )
. with_kind ( 10 )
. with_system ( false )
. with_level ( 2 )
. with_present ( true ) ;
// .- present
// | .- level
// | | .- system
// | | | .- kind
assert_eq ! ( my_byte_lsb . 0 , 0b1_10_0_1010 ) ;매크로는 MSB (가장 중요한 비트)가 지정 될 때 역 순서를 생성합니다.
use bitfield_struct :: bitfield ;
# [ bitfield ( u8 , order = Msb ) ]
struct MyMsbByte {
/// The first field occupies the *most* significant bits
# [ bits ( 4 ) ]
kind : usize ,
system : bool ,
# [ bits ( 2 ) ]
level : usize ,
present : bool
}
let my_byte_msb = MyMsbByte :: new ( )
. with_kind ( 10 )
. with_system ( false )
. with_level ( 2 )
. with_present ( true ) ;
// .- kind
// | .- system
// | | .- level
// | | | .- present
assert_eq ! ( my_byte_msb . 0 , 0b1010_0_10_1 ) ; 매크로는 비트 필드 구조물 표현을위한 사용자 정의 유형을 지원합니다. 이것은 다음 예제 ( endian-num 에서)와 같이 엔디 언 정의 유형 또는 기본 비트 필드 유형으로 전환 할 수있는 다른 구조물 일 수 있습니다.
표현 및 변환 기능은 다음 #[bitfield] 매개 변수로 지정할 수 있습니다.
repr 비트 필드의 메모리 표현을 지정합니다frominto이 예제는 대기업 기계에서도 작은 목 바이트 주문이 있습니다.
use bitfield_struct :: bitfield ;
use endian_num :: le16 ;
# [ bitfield ( u16 , repr = le16 , from = le16 :: from_ne , into = le16 :: to_ne ) ]
struct MyLeBitfield {
# [ bits ( 4 ) ]
first_nibble : u8 ,
# [ bits ( 12 ) ]
other : u16 ,
}
let my_be_bitfield = MyLeBitfield :: new ( )
. with_first_nibble ( 0x1 )
. with_other ( 0x234 ) ;
assert_eq ! ( my_be_bitfield . into_bits ( ) . to_le_bytes ( ) , [ 0x41 , 0x23 ] ) ;이 예제는 리틀 엔디안 기계에서도 큰 목 바이트 주문이 있습니다.
use bitfield_struct :: bitfield ;
use endian_num :: be16 ;
# [ bitfield ( u16 , repr = be16 , from = be16 :: from_ne , into = be16 :: to_ne ) ]
struct MyBeBitfield {
# [ bits ( 4 ) ]
first_nibble : u8 ,
# [ bits ( 12 ) ]
other : u16 ,
}
let my_be_bitfield = MyBeBitfield :: new ( )
. with_first_nibble ( 0x1 )
. with_other ( 0x234 ) ;
assert_eq ! ( my_be_bitfield . into_bits ( ) . to_be_bytes ( ) , [ 0x23 , 0x41 ] ) ; Clone , Copy 기본적 으로이 매크로는 Clone 및 Copy 파생합니다. 유형 클로닝의 의미론에 필요한 경우 추가 clone 인수로이를 비활성화 할 수 있습니다 (예 : 유형은 클로닝되어야하는 소유 데이터에 대한 포인터가 있습니다). 이 경우 Clone 및 Copy 대한 자체 구현을 제공 할 수 있습니다.
use bitfield_struct :: bitfield ;
# [ bitfield ( u64 , clone = false ) ]
struct CustomClone {
data : u64
}
impl Clone for CustomClone {
fn clone ( & self ) -> Self {
Self :: new ( ) . with_data ( self . data ( ) )
}
}
// optionally:
impl Copy for CustomClone { }fmt::Debug , Default 기본적으로 #[derive(Debug, Default)] 에 의해 일반 스트러크 용으로 생성 된 것과 유사한 적절한 fmt::Debug 및 Default 구현을 생성합니다. 추가 debug 및 default 인수로이를 비활성화 할 수 있습니다.
use std :: fmt :: { Debug , Formatter , Result } ;
use bitfield_struct :: bitfield ;
# [ bitfield ( u64 , debug = false , default = false ) ]
struct CustomDebug {
data : u64
}
impl Debug for CustomDebug {
fn fmt ( & self , f : & mut Formatter < ' _ > ) -> Result {
write ! ( f , "0x{:x}" , self . data ( ) )
}
}
impl Default for CustomDebug {
fn default ( ) -> Self {
Self ( 123 )
}
}
let val = CustomDebug :: default ( ) ;
println ! ( "{val:?}" )defmt::Format 에 대한 지원 이 매크로는 추가 defmt 인수를 전달하여 기본 fmt::Debug 구현을 반영하는 defmt::Format 자동으로 구현할 수 있습니다. 이 구현은 DEFMT 크레이트를 defmt 로 사용할 수 있어야하며 #[derive(defmt::Format)] 와 동일한 규칙과 경고를 가지고 있습니다.
use bitfield_struct :: bitfield ;
# [ bitfield ( u64 , defmt = true ) ]
struct DefmtExample {
data : u64
}new / Clone / Debug / Default / defmt::Format 활성화 부울 대신 new , clone , debug , default 및 defmt 에 대한 cfg(...) 속성을 지정할 수 있습니다.
use bitfield_struct :: bitfield ;
# [ bitfield ( u64 , debug = cfg ( test ) , default = cfg ( feature = "foo" ) ) ]
struct CustomDebug {
data : u64
}