// Copyright 2018 The ChromiumOS Authors1// Use of this source code is governed by a BSD-style license that can be2// found in the LICENSE file.34//! This crate provides a `#[bitfield]` attribute macro for defining structs in5//! a packed binary representation that supports access to ranges of bits.6//!7//! We conceptualize one of these structs as a sequence of bits 0..N. The bits8//! are grouped into fields in the order specified by a struct written by the9//! caller. The `#[bitfield]` attribute rewrites the caller's struct into a10//! private byte array representation with public getter and setter methods for11//! each field.12//!13//! Byte order: note that we consider the bit `i` to be the `i % 8`'th least14//! significant bit in the `i / 8`'th byte of the struct.15//!16//! The total number of bits N is required to be a multiple of 8 (this is17//! checked at compile time).18//!19//! # Examples20//!21//! The following invocation builds a struct with a total size of 32 bits or 422//! bytes. It places field `a` in the least significant bit of the first byte,23//! field `b` in the next three least significant bits, field `c` in the24//! remaining four most significant bits of the first byte, and field `d`25//! spanning the next three bytes. The least significant byte of `d` will be26//! held in the second byte of our struct, adjacent to the byte holding the27//! first three fields.28//!29//! ```30//! use bit_field::*;31//!32//! #[bitfield]33//! pub struct MyFourBytes {34//! a: B1,35//! b: B3,36//! c: B4,37//! d: B24,38//! }39//! ```40//!41//! ```text42//! less significant43//! / more significant44//! / /45//! (first byte) (second byte) / (third) / (fourth byte)46//! 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 747//! | \ / \_ _/ \_______________________ _______________________/48//! a b c less significant d more significant49//! ```50//!51//! The code emitted by the `#[bitfield]` macro for this struct is as follows.52//! Note that the field getters and setters use whichever of `u8`, `u16`, `u32`,53//! `u64` is the smallest while being at least as large as the number of bits in54//! the field.55//!56//! ```ignore57//! impl MyFourBytes {58//! // Initializes all fields to 0.59//! pub fn new() -> Self;60//!61//! // Field getters and setters:62//! pub fn get_a(&self) -> u8;63//! pub fn set_a(&mut self, val: u8);64//! pub fn get_b(&self) -> u8;65//! pub fn set_b(&mut self, val: u8);66//! pub fn get_c(&self) -> u8;67//! pub fn set_c(&mut self, val: u8);68//! pub fn get_d(&self) -> u32;69//! pub fn set_d(&mut self, val: u32);70//!71//! // Bit-level accessors:72//! pub fn get_bit(&self, offset: usize) -> bool;73//! pub fn set_bit(&mut self, offset: usize, val: bool);74//! pub fn get(&self, offset: usize, width: u8) -> u64;75//! pub fn set(&mut self, offset: usize, width: u8, val: u64);76//! }77//! ```78//!79//! # Bit field specifier types80//!81//! Field types may be specified as B1 through B64, or alternatively as82//! BitField1 through BitField64 in code that benefits from the clarification.83//!84//! Fields may also be specified as `bool`, which is laid out equivalently to85//! `B1` but with accessors that use `bool` rather than `u8`.86//!87//! ```88//! use bit_field::*;89//!90//! #[bitfield]91//! pub struct MyFourBytes {92//! a: bool,93//! b: B3,94//! c: B4,95//! d: B24,96//! }97//! ```98//!99//! Fields may be user-defined single element tuple struct with primitive types. Use must specify100//! the width with `#[bits = N]`. This should be used to improve type safety.101//!102//! ```103//! use bit_field::*;104//!105//! #[bitfield]106//! #[bits = 60]107//! struct AddressField(u64);108//!109//! impl AddressField {110//! pub fn new(addr: u64) -> AddressField {111//! AddressField(addr >> 4)112//! }113//!114//! pub fn get_addr(&self) -> u64 {115//! self.0 << 4116//! }117//! }118//! ```119//!120//! Finally, fields may be of user-defined enum types. The enum must satisfy one of the following121//! requirements.122//!123//! The enum has `#[bits = N]` attributes with it. `N` will be the width of the field. The getter124//! function of this enum field will return `Result<EnumType, u64>`. Raw value that does not match125//! any variant will result in an `Err(u64)`.126//!127//! ```128//! use bit_field::*;129//!130//! #[bitfield]131//! #[bits = 2]132//! #[derive(Debug, PartialEq)]133//! enum TwoBits {134//! Zero = 0b00,135//! One = 0b01,136//! Three = 0b11,137//! }138//!139//! #[bitfield]140//! struct Struct {141//! prefix: BitField1,142//! two_bits: TwoBits,143//! suffix: BitField5,144//! }145//! ```146//!147//! The enum has a number of variants which is a power of 2 and the discriminant values148//! (explicit or implicit) are 0 through (2^n)-1. In this case the generated149//! getter and setter are defined in terms of the given enum type.150//!151//! ```152//! use bit_field::*;153//!154//! #[bitfield]155//! #[derive(Debug, PartialEq)]156//! enum TwoBits {157//! Zero = 0b00,158//! One = 0b01,159//! Two = 0b10,160//! Three = 0b11,161//! }162//!163//! #[bitfield]164//! struct Struct {165//! prefix: BitField1,166//! two_bits: TwoBits,167//! suffix: BitField5,168//! }169//! ```170//!171//! An optional `#[bits = N]` attribute may be used to document the number of172//! bits in any field. This is intended for fields of enum type whose name does173//! not clearly indicate the number of bits. The attribute is optional but helps174//! make it possible to read off the field sizes directly from the definition of175//! a bitfield struct.176//!177//! ```178//! use bit_field::*;179//!180//! #[bitfield]181//! #[derive(Debug, PartialEq)]182//! enum WhoKnows {183//! Zero = 0b00,184//! One = 0b01,185//! Two = 0b10,186//! Three = 0b11,187//! }188//!189//! #[bitfield]190//! struct Struct {191//! prefix: BitField1,192//! #[bits = 2]193//! two_bits: WhoKnows,194//! suffix: BitField5,195//! }196//! ```197//!198//! # Derives199//!200//! Derives may be specified and are applied to the data structure post201//! rewriting by the macro.202//!203//! ```204//! use bit_field::*;205//!206//! #[bitfield]207//! #[derive(Copy, Clone)]208//! pub struct ExampleWithDerives {209//! car: B4,210//! cdr: B4,211//! }212//! ```213//!214//! # Compile time checks215//!216//! If the total size is not a multiple of 8 bits, you will receive an error217//! message at compile time mentioning:218//!219//! > the trait `bit_field::checks::TotalSizeIsMultipleOfEightBits` is not implemented220//!221//! ```compile_fail222//! use bit_field::*;223//!224//! #[bitfield]225//! pub struct Broken {226//! field_a: B1,227//! field_b: B3,228//! field_c: B6,229//! }230//! ```231//!232//! If a bitfield enum has discriminants that are outside the range 0 through233//! (2^n)-1, it will be caught at compile time.234//!235//! ```compile_fail236//! use bit_field::*;237//!238//! #[bitfield]239//! enum Broken {240//! Zero = 0b00,241//! One = 0b01,242//! Two = 0b10,243//! Nine = 0b1001, // error244//! }245//! ```246//!247//! If the value provided in a #[bits = N] attribute does not match the real248//! number of bits in that field, it will be caught.249//!250//! ```compile_fail251//! use bit_field::*;252//!253//! #[bitfield]254//! #[derive(Debug, PartialEq)]255//! enum OneBit {256//! No = 0,257//! Yes = 1,258//! }259//!260//! #[bitfield]261//! struct Struct {262//! #[bits = 4] // error263//! two_bits: OneBit,264//! padding: BitField7,265//! }266//! ```267268use std::fmt;269use std::fmt::Display;270271pub use bit_field_derive::bitfield;272273/// Error type for bit field get.274#[derive(Debug)]275pub struct Error {276type_name: &'static str,277val: u64,278}279280impl Error {281pub fn new(type_name: &'static str, val: u64) -> Error {282Error { type_name, val }283}284285pub fn raw_val(&self) -> u64 {286self.val287}288}289290impl Display for Error {291fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {292write!(293f,294"enum field type {} has a bad value {}",295self.type_name, self.val296)297}298}299300impl std::error::Error for Error {}301302#[doc(hidden)]303pub trait BitFieldSpecifier {304// Width of this field in bits.305const FIELD_WIDTH: u8;306// Date type for setter of this field.307// For any field, we use the closest u* type. e.g. FIELD_WIDTH <= 8 will308// have defulat type of u8.309// It's possible to write a custom specifier and use i8.310type SetterType;311// Data type for getter of this field. For enums, it will be Result<EnumType, SetterType>.312// For others, it will be the same as SetterType.313type GetterType;314315fn from_u64(val: u64) -> Self::GetterType;316fn into_u64(val: Self::SetterType) -> u64;317}318319// Largest u64 representable by this bit field specifier. Used by generated code320// in bit_field_derive.321#[doc(hidden)]322#[inline]323pub fn max<T: BitFieldSpecifier>() -> u64 {324if T::FIELD_WIDTH < 64 {325(1 << T::FIELD_WIDTH) - 1326} else {327u64::MAX328}329}330331// Defines bit_field::BitField0 through bit_field::BitField64.332bit_field_derive::define_bit_field_specifiers!();333334impl BitFieldSpecifier for bool {335const FIELD_WIDTH: u8 = 1;336type SetterType = bool;337type GetterType = bool;338339#[inline]340fn from_u64(val: u64) -> Self::GetterType {341val > 0342}343344#[inline]345fn into_u64(val: Self::SetterType) -> u64 {346val as u64347}348}349350// Instantiated by the generated code to prove that the total size of fields is351// a multiple of 8 bits.352#[doc(hidden)]353pub struct Check<T: checks::TotalSizeIsMultipleOfEightBits> {354marker: std::marker::PhantomData<T>,355}356357mod checks {358pub trait TotalSizeIsMultipleOfEightBits {}359impl TotalSizeIsMultipleOfEightBits for [u8; 0] {}360}361362363