• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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