Change default field type to setter/getter types and remove generated

tests

Setter/Getter types will allow better enum fields.
Generated tests should be tests for bit_field cargo rather than the
defined bit_field struct.

BUG=None
TEST=cargo test

Change-Id: Ib3594e35e28fc393d49c476c9c83fc632cac3190
Reviewed-on: https://chromium-review.googlesource.com/1530454
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Tested-by: Jingkui Wang <jkwang@google.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: David Tolnay <dtolnay@chromium.org>
This commit is contained in:
Jingkui Wang 2019-03-18 11:22:32 -07:00 committed by chrome-bot
parent 96e26c2681
commit ca224cd547
2 changed files with 28 additions and 149 deletions

View file

@ -151,10 +151,11 @@ fn bitfield_enum_impl(ast: &DeriveInput, data: &DataEnum) -> Result<TokenStream>
impl bit_field::BitFieldSpecifier for #ident {
const FIELD_WIDTH: u8 = #bits;
type DefaultFieldType = Self;
type SetterType = Self;
type GetterType = Self;
#[inline]
fn from_u64(val: u64) -> Self::DefaultFieldType {
fn from_u64(val: u64) -> Self::GetterType {
struct discriminant;
impl discriminant {
#(#declare_discriminants)*
@ -166,7 +167,7 @@ fn bitfield_enum_impl(ast: &DeriveInput, data: &DataEnum) -> Result<TokenStream>
}
#[inline]
fn into_u64(val: Self::DefaultFieldType) -> u64 {
fn into_u64(val: Self::SetterType) -> u64 {
val as u64
}
}
@ -177,17 +178,12 @@ fn bitfield_enum_impl(ast: &DeriveInput, data: &DataEnum) -> Result<TokenStream>
fn bitfield_struct_impl(ast: &DeriveInput, fields: &FieldsNamed) -> Result<TokenStream> {
let name = &ast.ident;
let test_mod_ident = Ident::new(
format!("test_{}", name.to_string().to_lowercase()).as_str(),
Span::call_site(),
);
let vis = &ast.vis;
let attrs = &ast.attrs;
let fields = get_struct_fields(fields)?;
let struct_def = get_struct_def(vis, &name, &fields);
let bits_impl = get_bits_impl(&name);
let fields_impl = get_fields_impl(&fields);
let tests_impl = get_tests_impl(&name, &fields);
let debug_fmt_impl = get_debug_fmt_impl(&name, &fields);
let expanded = quote! {
@ -197,13 +193,7 @@ fn bitfield_struct_impl(ast: &DeriveInput, fields: &FieldsNamed) -> Result<Token
impl #name {
#(#fields_impl)*
}
#debug_fmt_impl
#[cfg(test)]
mod #test_mod_ident {
use super::*;
#(#tests_impl)*
}
};
Ok(expanded)
@ -320,14 +310,14 @@ fn get_fields_impl(fields: &[FieldSpec]) -> Vec<TokenStream> {
});
impls.push(quote! {
pub fn #getter_ident(&self) -> <#ty as ::bit_field::BitFieldSpecifier>::DefaultFieldType {
pub fn #getter_ident(&self) -> <#ty as ::bit_field::BitFieldSpecifier>::GetterType {
#check_expected_bits
let offset = #(<#current_types as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize)+*;
let val = self.get(offset, <#ty as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH);
<#ty as ::bit_field::BitFieldSpecifier>::from_u64(val)
}
pub fn #setter_ident(&mut self, val: <#ty as ::bit_field::BitFieldSpecifier>::DefaultFieldType) {
pub fn #setter_ident(&mut self, val: <#ty as ::bit_field::BitFieldSpecifier>::SetterType) {
let val = <#ty as ::bit_field::BitFieldSpecifier>::into_u64(val);
debug_assert!(val <= ::bit_field::max::<#ty>());
let offset = #(<#current_types as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize)+*;
@ -365,62 +355,6 @@ fn get_debug_fmt_impl(name: &Ident, fields: &[FieldSpec]) -> TokenStream {
}
}
// Implement test.
fn get_tests_impl(struct_name: &Ident, fields: &[FieldSpec]) -> Vec<TokenStream> {
let mut field_types = Vec::new();
for spec in fields {
field_types.push(spec.ty);
}
let field_types2 = field_types.clone();
let mut impls = Vec::new();
impls.push(quote! {
#[test]
fn test_total_size() {
let total_size = #(<#field_types as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize)+*;
assert_eq!(total_size % 8, 0);
}
});
impls.push(quote! {
#[test]
fn test_bits_boundary() {
let fields_sizes = vec![#(<#field_types2 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize),*];
let mut sum = 0usize;
for s in fields_sizes {
if sum % 64 == 0 {
assert!(s <= 64);
} else {
if (sum + s) % 64 != 0 {
assert_eq!(sum / 64, (sum + s) / 64);
}
}
sum += s;
}
}
});
for spec in fields {
let testname = Ident::new(&format!("test_{}", spec.ident), Span::call_site());
let getter_ident = Ident::new(&format!("get_{}", spec.ident), Span::call_site());
let setter_ident = Ident::new(&format!("set_{}", spec.ident), Span::call_site());
let ty = spec.ty;
impls.push(quote! {
#[test]
fn #testname() {
let mut a = #struct_name::new();
let val = <#ty as ::bit_field::BitFieldSpecifier>::into_u64(a.#getter_ident());
assert_eq!(val, 0);
let val = <#ty as ::bit_field::BitFieldSpecifier>::from_u64(::bit_field::max::<#ty>());
a.#setter_ident(val);
let val = <#ty as ::bit_field::BitFieldSpecifier>::into_u64(a.#getter_ident());
assert_eq!(val, ::bit_field::max::<#ty>());
}
});
}
impls
}
fn get_bits_impl(name: &Ident) -> TokenStream {
quote! {
impl #name {
@ -517,15 +451,16 @@ pub fn define_bit_field_specifiers(_input: proc_macro::TokenStream) -> proc_macr
impl BitFieldSpecifier for #long_name {
const FIELD_WIDTH: u8 = #width;
type DefaultFieldType = #default_field_type;
type SetterType = #default_field_type;
type GetterType = #default_field_type;
#[inline]
fn from_u64(val: u64) -> Self::DefaultFieldType {
val as Self::DefaultFieldType
fn from_u64(val: u64) -> Self::GetterType {
val as Self::GetterType
}
#[inline]
fn into_u64(val: Self::DefaultFieldType) -> u64 {
fn into_u64(val: Self::SetterType) -> u64 {
val as u64
}
}
@ -628,38 +563,38 @@ mod tests {
}
}
impl MyBitField {
pub fn get_a(&self) -> <BitField1 as ::bit_field::BitFieldSpecifier>::DefaultFieldType {
pub fn get_a(&self) -> <BitField1 as ::bit_field::BitFieldSpecifier>::GetterType {
let offset = <::bit_field::BitField0 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize;
let val = self.get(offset, <BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH);
<BitField1 as ::bit_field::BitFieldSpecifier>::from_u64(val)
}
pub fn set_a(&mut self, val: <BitField1 as ::bit_field::BitFieldSpecifier>::DefaultFieldType) {
pub fn set_a(&mut self, val: <BitField1 as ::bit_field::BitFieldSpecifier>::SetterType) {
let val = <BitField1 as ::bit_field::BitFieldSpecifier>::into_u64(val);
debug_assert!(val <= ::bit_field::max::<BitField1>());
let offset = <::bit_field::BitField0 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize;
self.set(offset, <BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH, val)
}
pub fn get_b(&self) -> <BitField2 as ::bit_field::BitFieldSpecifier>::DefaultFieldType {
pub fn get_b(&self) -> <BitField2 as ::bit_field::BitFieldSpecifier>::GetterType {
let offset = <::bit_field::BitField0 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
+ <BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize;
let val = self.get(offset, <BitField2 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH);
<BitField2 as ::bit_field::BitFieldSpecifier>::from_u64(val)
}
pub fn set_b(&mut self, val: <BitField2 as ::bit_field::BitFieldSpecifier>::DefaultFieldType) {
pub fn set_b(&mut self, val: <BitField2 as ::bit_field::BitFieldSpecifier>::SetterType) {
let val = <BitField2 as ::bit_field::BitFieldSpecifier>::into_u64(val);
debug_assert!(val <= ::bit_field::max::<BitField2>());
let offset = <::bit_field::BitField0 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
+ <BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize;
self.set(offset, <BitField2 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH, val)
}
pub fn get_c(&self) -> <BitField5 as ::bit_field::BitFieldSpecifier>::DefaultFieldType {
pub fn get_c(&self) -> <BitField5 as ::bit_field::BitFieldSpecifier>::GetterType {
let offset = <::bit_field::BitField0 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
+ <BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
+ <BitField2 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize;
let val = self.get(offset, <BitField5 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH);
<BitField5 as ::bit_field::BitFieldSpecifier>::from_u64(val)
}
pub fn set_c(&mut self, val: <BitField5 as ::bit_field::BitFieldSpecifier>::DefaultFieldType) {
pub fn set_c(&mut self, val: <BitField5 as ::bit_field::BitFieldSpecifier>::SetterType) {
let val = <BitField5 as ::bit_field::BitFieldSpecifier>::into_u64(val);
debug_assert!(val <= ::bit_field::max::<BitField5>());
let offset = <::bit_field::BitField0 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
@ -677,66 +612,6 @@ mod tests {
.finish()
}
}
#[cfg(test)]
mod test_mybitfield {
use super::*;
#[test]
fn test_total_size() {
let total_size = <BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
+ <BitField2 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
+ <BitField5 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize;
assert_eq!(total_size % 8, 0);
}
#[test]
fn test_bits_boundary() {
let fields_sizes = vec![
<BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize,
<BitField2 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize,
<BitField5 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
];
let mut sum = 0usize;
for s in fields_sizes {
if sum % 64 == 0 {
assert!(s <= 64);
} else {
if (sum + s) % 64 != 0 {
assert_eq!(sum / 64, (sum + s) / 64);
}
}
sum += s;
}
}
#[test]
fn test_a() {
let mut a = MyBitField::new();
let val = <BitField1 as ::bit_field::BitFieldSpecifier>::into_u64(a.get_a());
assert_eq!(val, 0);
let val = <BitField1 as ::bit_field::BitFieldSpecifier>::from_u64(::bit_field::max::<BitField1>());
a.set_a(val);
let val = <BitField1 as ::bit_field::BitFieldSpecifier>::into_u64(a.get_a());
assert_eq!(val, ::bit_field::max::<BitField1>());
}
#[test]
fn test_b() {
let mut a = MyBitField::new();
let val = <BitField2 as ::bit_field::BitFieldSpecifier>::into_u64(a.get_b());
assert_eq!(val, 0);
let val = <BitField2 as ::bit_field::BitFieldSpecifier>::from_u64(::bit_field::max::<BitField2>());
a.set_b(val);
let val = <BitField2 as ::bit_field::BitFieldSpecifier>::into_u64(a.get_b());
assert_eq!(val, ::bit_field::max::<BitField2>());
}
#[test]
fn test_c() {
let mut a = MyBitField::new();
let val = <BitField5 as ::bit_field::BitFieldSpecifier>::into_u64(a.get_c());
assert_eq!(val, 0);
let val = <BitField5 as ::bit_field::BitFieldSpecifier>::from_u64(::bit_field::max::<BitField5>());
a.set_c(val);
let val = <BitField5 as ::bit_field::BitFieldSpecifier>::into_u64(a.get_c());
assert_eq!(val, ::bit_field::max::<BitField5>());
}
}
};
assert_eq!(

View file

@ -245,14 +245,17 @@ pub use bit_field_derive::bitfield;
pub trait BitFieldSpecifier {
// Width of this field in bits.
const FIELD_WIDTH: u8;
// Default data type of this field.
// Date type for setter 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;
type SetterType;
// Data type for getter of this field. For enums, it will be Result<EnumType, SetterType>.
// For others, it will be the same as SetterType.
type GetterType;
fn from_u64(val: u64) -> Self::DefaultFieldType;
fn into_u64(val: Self::DefaultFieldType) -> u64;
fn from_u64(val: u64) -> Self::GetterType;
fn into_u64(val: Self::SetterType) -> u64;
}
// Largest u64 representable by this bit field specifier. Used by generated code
@ -272,15 +275,16 @@ bit_field_derive::define_bit_field_specifiers!();
impl BitFieldSpecifier for bool {
const FIELD_WIDTH: u8 = 1;
type DefaultFieldType = bool;
type SetterType = bool;
type GetterType = bool;
#[inline]
fn from_u64(val: u64) -> Self::DefaultFieldType {
fn from_u64(val: u64) -> Self::GetterType {
val > 0
}
#[inline]
fn into_u64(val: Self::DefaultFieldType) -> u64 {
fn into_u64(val: Self::SetterType) -> u64 {
val as u64
}
}