1 // Copyright 2018 The Chromium OS Authors. All rights reserved.
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 //!
122 //! Finally, fields may be of user-defined enum types. The enum must satisfy one of the following
123 //! requirements.
124 //!
125 //! The enum has `#[bits = N]` attributes with it. `N` will be the width of the field. The getter
126 //! function of this enum field will return `Result<EnumType, u64>`. Raw value that does not match
127 //! any variant will result in an `Err(u64)`.
128 //!
129 //! ```
130 //! use bit_field::*;
131 //!
132 //! #[bitfield]
133 //! #[bits = 2]
134 //! #[derive(Debug, PartialEq)]
135 //! enum TwoBits {
136 //! Zero = 0b00,
137 //! One = 0b01,
138 //! Three = 0b11,
139 //! }
140 //!
141 //! #[bitfield]
142 //! struct Struct {
143 //! prefix: BitField1,
144 //! two_bits: TwoBits,
145 //! suffix: BitField5,
146 //! }
147 //! ```
148 //!
149 //! The enum has a number of variants which is a power of 2 and the discriminant values
150 //! (explicit or implicit) are 0 through (2^n)-1. In this case the generated
151 //! getter and setter are defined in terms of the given enum type.
152 //!
153 //! ```
154 //! use bit_field::*;
155 //!
156 //! #[bitfield]
157 //! #[derive(Debug, PartialEq)]
158 //! enum TwoBits {
159 //! Zero = 0b00,
160 //! One = 0b01,
161 //! Two = 0b10,
162 //! Three = 0b11,
163 //! }
164 //!
165 //! #[bitfield]
166 //! struct Struct {
167 //! prefix: BitField1,
168 //! two_bits: TwoBits,
169 //! suffix: BitField5,
170 //! }
171 //! ```
172 //!
173 //! An optional `#[bits = N]` attribute may be used to document the number of
174 //! bits in any field. This is intended for fields of enum type whose name does
175 //! not clearly indicate the number of bits. The attribute is optional but helps
176 //! make it possible to read off the field sizes directly from the definition of
177 //! a bitfield struct.
178 //!
179 //! ```
180 //! use bit_field::*;
181 //!
182 //! #[bitfield]
183 //! #[derive(Debug, PartialEq)]
184 //! enum WhoKnows {
185 //! Zero = 0b00,
186 //! One = 0b01,
187 //! Two = 0b10,
188 //! Three = 0b11,
189 //! }
190 //!
191 //! #[bitfield]
192 //! struct Struct {
193 //! prefix: BitField1,
194 //! #[bits = 2]
195 //! two_bits: WhoKnows,
196 //! suffix: BitField5,
197 //! }
198 //! ```
199 //!
200 //! # Derives
201 //!
202 //! Derives may be specified and are applied to the data structure post
203 //! rewriting by the macro.
204 //!
205 //! ```
206 //! use bit_field::*;
207 //!
208 //! #[bitfield]
209 //! #[derive(Copy, Clone)]
210 //! pub struct ExampleWithDerives {
211 //! car: B4,
212 //! cdr: B4,
213 //! }
214 //! ```
215 //!
216 //! # Compile time checks
217 //!
218 //! If the total size is not a multiple of 8 bits, you will receive an error
219 //! message at compile time mentioning:
220 //!
221 //! > the trait `bit_field::checks::TotalSizeIsMultipleOfEightBits` is not implemented
222 //!
223 //! ```compile_fail
224 //! use bit_field::*;
225 //!
226 //! #[bitfield]
227 //! pub struct Broken {
228 //! field_a: B1,
229 //! field_b: B3,
230 //! field_c: B6,
231 //! }
232 //! ```
233 //!
234 //! If a bitfield enum has discriminants that are outside the range 0 through
235 //! (2^n)-1, it will be caught at compile time.
236 //!
237 //! ```compile_fail
238 //! use bit_field::*;
239 //!
240 //! #[bitfield]
241 //! enum Broken {
242 //! Zero = 0b00,
243 //! One = 0b01,
244 //! Two = 0b10,
245 //! Nine = 0b1001, // error
246 //! }
247 //! ```
248 //!
249 //! If the value provided in a #[bits = N] attribute does not match the real
250 //! number of bits in that field, it will be caught.
251 //!
252 //! ```compile_fail
253 //! use bit_field::*;
254 //!
255 //! #[bitfield]
256 //! #[derive(Debug, PartialEq)]
257 //! enum OneBit {
258 //! No = 0,
259 //! Yes = 1,
260 //! }
261 //!
262 //! #[bitfield]
263 //! struct Struct {
264 //! #[bits = 4] // error
265 //! two_bits: OneBit,
266 //! padding: BitField7,
267 //! }
268 //! ```
269
270 use std::fmt::{self, 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_value()
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