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