blob: aa943a30de209a3896d027e773d7670c9a0846ff [file] [log] [blame]
// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#[allow(unused_imports)]
#[macro_use]
extern crate bit_field_derive;
pub use bit_field_derive::*;
// This functions calculate max possible number represented by `width` bits. If one day this can be
// done in other ways, remove this function. For now, stop worrying and trust constant
// propagation. (checked assembly code, it's a constant when opt-leve >= 2)
fn max_number_of_width(width: u8) -> u64 {
if width < 64 {
(1 << width) - 1
} else {
u64::max_value()
}
}
/// BitFieldSpecifier is a group of structs help defining bitfield. It should only
/// be used with the #[bitfield] attribute macro.
/// Example:
/// #[bitfield]
/// pub struct MyBitFieldSchema {
/// field_a : BitField1,
/// field_b : BitField3,
/// field_c : BitField5,
/// field_d : BitField32,
/// }
///
/// bit_field_derive implementation will use the static informations associated
/// with those tyes to generate a struct named MyBitField and getter/setter for
/// all fields.
/// An example getter/setter is:
/// fn get_field_a(&self) -> u8
/// fn set_field_a(&self, val: u8)
/// For larger fields:
/// fn get_field_d(&self) -> u32
/// fn set_field_d(&self, val: u32)
///
/// You can also pass attributes to the defined bitfield structs. Simply do this:
/// #[derive(Clone)]
/// For more details, refer to bit_field_derive.
pub trait BitFieldSpecifier {
/// Width of this field in bits.
const FIELD_WIDTH: u8;
/// Default data type of this field.
/// For any field, we use the closest u* type. e.g. FIELD_WIDTH <= 8 will
/// have defulat type of u8.
/// It's possible to write a custom specifier and use i8.
type DefaultFieldType;
/// Max value of this field.
fn field_max() -> u64 {
max_number_of_width(Self::FIELD_WIDTH)
}
fn from_u64(val: u64) -> Self::DefaultFieldType;
fn into_u64(val: Self::DefaultFieldType) -> u64;
}
pub struct BitFieldBool;
impl BitFieldSpecifier for BitFieldBool {
const FIELD_WIDTH: u8 = 1;
type DefaultFieldType = bool;
fn from_u64(val: u64) -> Self::DefaultFieldType {
val > 0
}
fn into_u64(val: Self::DefaultFieldType) -> u64 {
val as u64
}
}
macro_rules! bitfield_structs {
($t:ty, $min_width:expr, $bt:ident $($bts:ident)*)
=> {
pub struct $bt;
impl BitFieldSpecifier for $bt {
const FIELD_WIDTH: u8 = $min_width;
type DefaultFieldType = $t;
fn from_u64(val: u64) -> Self::DefaultFieldType {
val as Self::DefaultFieldType
}
fn into_u64(val: Self::DefaultFieldType) -> u64 {
val as u64
}
}
bitfield_structs!($t, $min_width + 1, $($bts)*);
};
($t:ty, $min_width:expr,) => {};
}
bitfield_structs! {
u8, 0, BitField0 BitField1 BitField2 BitField3 BitField4 BitField5 BitField6 BitField7 BitField8
}
bitfield_structs! {
u16, 9, BitField9 BitField10 BitField11 BitField12 BitField13 BitField14 BitField15 BitField16
}
bitfield_structs! {
u32, 17, BitField17 BitField18 BitField19 BitField20 BitField21 BitField22 BitField23 BitField24
BitField25 BitField26 BitField27 BitField28 BitField29 BitField30 BitField31 BitField32
}
bitfield_structs! {
u64, 33, BitField33 BitField34 BitField35 BitField36 BitField37 BitField38 BitField39 BitField40 BitField41
BitField42 BitField43 BitField44 BitField45 BitField46 BitField47 BitField48 BitField49 BitField50
BitField51 BitField52 BitField53 BitField54 BitField55 BitField56 BitField57 BitField58
BitField59 BitField60 BitField61 BitField62 BitField63 BitField64
}