xref: /aosp_15_r20/external/crosvm/bit_field/src/lib.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2018 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 //! This crate provides a `#[bitfield]` attribute macro for defining structs in
6 //! a packed binary representation that supports access to ranges of bits.
7 //!
8 //! We conceptualize one of these structs as a sequence of bits 0..N. The bits
9 //! are grouped into fields in the order specified by a struct written by the
10 //! caller. The `#[bitfield]` attribute rewrites the caller's struct into a
11 //! private byte array representation with public getter and setter methods for
12 //! each field.
13 //!
14 //! Byte order: note that we consider the bit `i` to be the `i % 8`'th least
15 //! significant bit in the `i / 8`'th byte of the struct.
16 //!
17 //! The total number of bits N is required to be a multiple of 8 (this is
18 //! checked at compile time).
19 //!
20 //! # Examples
21 //!
22 //! The following invocation builds a struct with a total size of 32 bits or 4
23 //! bytes. It places field `a` in the least significant bit of the first byte,
24 //! field `b` in the next three least significant bits, field `c` in the
25 //! remaining four most significant bits of the first byte, and field `d`
26 //! spanning the next three bytes. The least significant byte of `d` will be
27 //! held in the second byte of our struct, adjacent to the byte holding the
28 //! first three fields.
29 //!
30 //! ```
31 //! use bit_field::*;
32 //!
33 //! #[bitfield]
34 //! pub struct MyFourBytes {
35 //!     a: B1,
36 //!     b: B3,
37 //!     c: B4,
38 //!     d: B24,
39 //! }
40 //! ```
41 //!
42 //! ```text
43 //!                                             less significant
44 //!                                            /             more significant
45 //!                                           /             /
46 //!      (first byte)      (second byte)     /   (third)   /   (fourth byte)
47 //!     0 1 2 3 4 5 6 7   0 1 2 3 4 5 6 7   0 1 2 3 4 5 6 7   0 1 2 3 4 5 6 7
48 //!     |  \ /   \_ _/     \_______________________ _______________________/
49 //!     a   b      c        less significant       d       more significant
50 //! ```
51 //!
52 //! The code emitted by the `#[bitfield]` macro for this struct is as follows.
53 //! Note that the field getters and setters use whichever of `u8`, `u16`, `u32`,
54 //! `u64` is the smallest while being at least as large as the number of bits in
55 //! the field.
56 //!
57 //! ```ignore
58 //! impl MyFourBytes {
59 //!     // Initializes all fields to 0.
60 //!     pub fn new() -> Self;
61 //!
62 //!     // Field getters and setters:
63 //!     pub fn get_a(&self) -> u8;
64 //!     pub fn set_a(&mut self, val: u8);
65 //!     pub fn get_b(&self) -> u8;
66 //!     pub fn set_b(&mut self, val: u8);
67 //!     pub fn get_c(&self) -> u8;
68 //!     pub fn set_c(&mut self, val: u8);
69 //!     pub fn get_d(&self) -> u32;
70 //!     pub fn set_d(&mut self, val: u32);
71 //!
72 //!     // Bit-level accessors:
73 //!     pub fn get_bit(&self, offset: usize) -> bool;
74 //!     pub fn set_bit(&mut self, offset: usize, val: bool);
75 //!     pub fn get(&self, offset: usize, width: u8) -> u64;
76 //!     pub fn set(&mut self, offset: usize, width: u8, val: u64);
77 //! }
78 //! ```
79 //!
80 //! # Bit field specifier types
81 //!
82 //! Field types may be specified as B1 through B64, or alternatively as
83 //! BitField1 through BitField64 in code that benefits from the clarification.
84 //!
85 //! Fields may also be specified as `bool`, which is laid out equivalently to
86 //! `B1` but with accessors that use `bool` rather than `u8`.
87 //!
88 //! ```
89 //! use bit_field::*;
90 //!
91 //! #[bitfield]
92 //! pub struct MyFourBytes {
93 //!     a: bool,
94 //!     b: B3,
95 //!     c: B4,
96 //!     d: B24,
97 //! }
98 //! ```
99 //!
100 //! Fields may be user-defined single element tuple struct with primitive types. Use must specify
101 //! the width with `#[bits = N]`. This should be used to improve type safety.
102 //!
103 //! ```
104 //! use bit_field::*;
105 //!
106 //! #[bitfield]
107 //! #[bits = 60]
108 //! struct AddressField(u64);
109 //!
110 //! impl AddressField {
111 //!     pub fn new(addr: u64) -> AddressField {
112 //!         AddressField(addr >> 4)
113 //!     }
114 //!
115 //!     pub fn get_addr(&self) -> u64 {
116 //!         self.0 << 4
117 //!     }
118 //! }
119 //! ```
120 //!
121 //! Finally, fields may be of user-defined enum types. The enum must satisfy one of the following
122 //! requirements.
123 //!
124 //! The enum has `#[bits = N]` attributes with it. `N` will be the width of the field. The getter
125 //! function of this enum field will return `Result<EnumType, u64>`. Raw value that does not match
126 //! any variant will result in an `Err(u64)`.
127 //!
128 //! ```
129 //! use bit_field::*;
130 //!
131 //! #[bitfield]
132 //! #[bits = 2]
133 //! #[derive(Debug, PartialEq)]
134 //! enum TwoBits {
135 //!     Zero = 0b00,
136 //!     One = 0b01,
137 //!     Three = 0b11,
138 //! }
139 //!
140 //! #[bitfield]
141 //! struct Struct {
142 //!     prefix: BitField1,
143 //!     two_bits: TwoBits,
144 //!     suffix: BitField5,
145 //! }
146 //! ```
147 //!
148 //! The enum has a number of variants which is a power of 2 and the discriminant values
149 //! (explicit or implicit) are 0 through (2^n)-1. In this case the generated
150 //! getter and setter are defined in terms of the given enum type.
151 //!
152 //! ```
153 //! use bit_field::*;
154 //!
155 //! #[bitfield]
156 //! #[derive(Debug, PartialEq)]
157 //! enum TwoBits {
158 //!     Zero = 0b00,
159 //!     One = 0b01,
160 //!     Two = 0b10,
161 //!     Three = 0b11,
162 //! }
163 //!
164 //! #[bitfield]
165 //! struct Struct {
166 //!     prefix: BitField1,
167 //!     two_bits: TwoBits,
168 //!     suffix: BitField5,
169 //! }
170 //! ```
171 //!
172 //! An optional `#[bits = N]` attribute may be used to document the number of
173 //! bits in any field. This is intended for fields of enum type whose name does
174 //! not clearly indicate the number of bits. The attribute is optional but helps
175 //! make it possible to read off the field sizes directly from the definition of
176 //! a bitfield struct.
177 //!
178 //! ```
179 //! use bit_field::*;
180 //!
181 //! #[bitfield]
182 //! #[derive(Debug, PartialEq)]
183 //! enum WhoKnows {
184 //!     Zero = 0b00,
185 //!     One = 0b01,
186 //!     Two = 0b10,
187 //!     Three = 0b11,
188 //! }
189 //!
190 //! #[bitfield]
191 //! struct Struct {
192 //!     prefix: BitField1,
193 //!     #[bits = 2]
194 //!     two_bits: WhoKnows,
195 //!     suffix: BitField5,
196 //! }
197 //! ```
198 //!
199 //! # Derives
200 //!
201 //! Derives may be specified and are applied to the data structure post
202 //! rewriting by the macro.
203 //!
204 //! ```
205 //! use bit_field::*;
206 //!
207 //! #[bitfield]
208 //! #[derive(Copy, Clone)]
209 //! pub struct ExampleWithDerives {
210 //!     car: B4,
211 //!     cdr: B4,
212 //! }
213 //! ```
214 //!
215 //! # Compile time checks
216 //!
217 //! If the total size is not a multiple of 8 bits, you will receive an error
218 //! message at compile time mentioning:
219 //!
220 //! > the trait `bit_field::checks::TotalSizeIsMultipleOfEightBits` is not implemented
221 //!
222 //! ```compile_fail
223 //! use bit_field::*;
224 //!
225 //! #[bitfield]
226 //! pub struct Broken {
227 //!     field_a: B1,
228 //!     field_b: B3,
229 //!     field_c: B6,
230 //! }
231 //! ```
232 //!
233 //! If a bitfield enum has discriminants that are outside the range 0 through
234 //! (2^n)-1, it will be caught at compile time.
235 //!
236 //! ```compile_fail
237 //! use bit_field::*;
238 //!
239 //! #[bitfield]
240 //! enum Broken {
241 //!     Zero = 0b00,
242 //!     One = 0b01,
243 //!     Two = 0b10,
244 //!     Nine = 0b1001, // error
245 //! }
246 //! ```
247 //!
248 //! If the value provided in a #[bits = N] attribute does not match the real
249 //! number of bits in that field, it will be caught.
250 //!
251 //! ```compile_fail
252 //! use bit_field::*;
253 //!
254 //! #[bitfield]
255 //! #[derive(Debug, PartialEq)]
256 //! enum OneBit {
257 //!     No = 0,
258 //!     Yes = 1,
259 //! }
260 //!
261 //! #[bitfield]
262 //! struct Struct {
263 //!     #[bits = 4] // error
264 //!     two_bits: OneBit,
265 //!     padding: BitField7,
266 //! }
267 //! ```
268 
269 use std::fmt;
270 use std::fmt::Display;
271 
272 pub use bit_field_derive::bitfield;
273 
274 /// Error type for bit field get.
275 #[derive(Debug)]
276 pub struct Error {
277     type_name: &'static str,
278     val: u64,
279 }
280 
281 impl Error {
new(type_name: &'static str, val: u64) -> Error282     pub fn new(type_name: &'static str, val: u64) -> Error {
283         Error { type_name, val }
284     }
285 
raw_val(&self) -> u64286     pub fn raw_val(&self) -> u64 {
287         self.val
288     }
289 }
290 
291 impl Display for Error {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result292     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
293         write!(
294             f,
295             "enum field type {} has a bad value {}",
296             self.type_name, self.val
297         )
298     }
299 }
300 
301 impl std::error::Error for Error {}
302 
303 #[doc(hidden)]
304 pub trait BitFieldSpecifier {
305     // Width of this field in bits.
306     const FIELD_WIDTH: u8;
307     // Date type for setter of this field.
308     // For any field, we use the closest u* type. e.g. FIELD_WIDTH <= 8 will
309     // have defulat type of u8.
310     // It's possible to write a custom specifier and use i8.
311     type SetterType;
312     // Data type for getter of this field. For enums, it will be Result<EnumType, SetterType>.
313     // For others, it will be the same as SetterType.
314     type GetterType;
315 
from_u64(val: u64) -> Self::GetterType316     fn from_u64(val: u64) -> Self::GetterType;
into_u64(val: Self::SetterType) -> u64317     fn into_u64(val: Self::SetterType) -> u64;
318 }
319 
320 // Largest u64 representable by this bit field specifier. Used by generated code
321 // in bit_field_derive.
322 #[doc(hidden)]
323 #[inline]
max<T: BitFieldSpecifier>() -> u64324 pub fn max<T: BitFieldSpecifier>() -> u64 {
325     if T::FIELD_WIDTH < 64 {
326         (1 << T::FIELD_WIDTH) - 1
327     } else {
328         u64::MAX
329     }
330 }
331 
332 // Defines bit_field::BitField0 through bit_field::BitField64.
333 bit_field_derive::define_bit_field_specifiers!();
334 
335 impl BitFieldSpecifier for bool {
336     const FIELD_WIDTH: u8 = 1;
337     type SetterType = bool;
338     type GetterType = bool;
339 
340     #[inline]
from_u64(val: u64) -> Self::GetterType341     fn from_u64(val: u64) -> Self::GetterType {
342         val > 0
343     }
344 
345     #[inline]
into_u64(val: Self::SetterType) -> u64346     fn into_u64(val: Self::SetterType) -> u64 {
347         val as u64
348     }
349 }
350 
351 // Instantiated by the generated code to prove that the total size of fields is
352 // a multiple of 8 bits.
353 #[doc(hidden)]
354 pub struct Check<T: checks::TotalSizeIsMultipleOfEightBits> {
355     marker: std::marker::PhantomData<T>,
356 }
357 
358 mod checks {
359     pub trait TotalSizeIsMultipleOfEightBits {}
360     impl TotalSizeIsMultipleOfEightBits for [u8; 0] {}
361 }
362