1 // Copyright 2018 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #![recursion_limit = "256"]
6
7 extern crate proc_macro;
8
9 use proc_macro2::Span;
10 use proc_macro2::TokenStream;
11 use quote::quote;
12 use quote::quote_spanned;
13 use syn::parse::Error;
14 use syn::parse::Result;
15 use syn::parse_macro_input;
16 use syn::Attribute;
17 use syn::Data;
18 use syn::DataEnum;
19 use syn::DeriveInput;
20 use syn::Fields;
21 use syn::FieldsNamed;
22 use syn::FieldsUnnamed;
23 use syn::Ident;
24 use syn::Lit;
25 use syn::LitInt;
26 use syn::Meta;
27 use syn::MetaNameValue;
28 use syn::Type;
29 use syn::Visibility;
30
31 /// The function that derives the actual implementation.
32 #[proc_macro_attribute]
bitfield( _args: proc_macro::TokenStream, input: proc_macro::TokenStream, ) -> proc_macro::TokenStream33 pub fn bitfield(
34 _args: proc_macro::TokenStream,
35 input: proc_macro::TokenStream,
36 ) -> proc_macro::TokenStream {
37 let derive_input = parse_macro_input!(input as DeriveInput);
38
39 let expanded = bitfield_impl(&derive_input).unwrap_or_else(|err| {
40 let compile_error = err.to_compile_error();
41 quote! {
42 #compile_error
43
44 // Include the original input to avoid "use of undeclared type"
45 // errors elsewhere.
46 #derive_input
47 }
48 });
49
50 expanded.into()
51 }
52
bitfield_impl(ast: &DeriveInput) -> Result<TokenStream>53 fn bitfield_impl(ast: &DeriveInput) -> Result<TokenStream> {
54 if !ast.generics.params.is_empty() {
55 return Err(Error::new(
56 Span::call_site(),
57 "#[bitfield] does not support generic parameters",
58 ));
59 }
60
61 match &ast.data {
62 Data::Struct(data_struct) => match &data_struct.fields {
63 Fields::Named(fields_named) => bitfield_struct_impl(ast, fields_named),
64 Fields::Unnamed(fields_unnamed) => bitfield_tuple_struct_impl(ast, fields_unnamed),
65 Fields::Unit => Err(Error::new(
66 Span::call_site(),
67 "#[bitfield] does not work with unit struct",
68 )),
69 },
70 Data::Enum(data_enum) => bitfield_enum_impl(ast, data_enum),
71 Data::Union(_) => Err(Error::new(
72 Span::call_site(),
73 "#[bitfield] does not support unions",
74 )),
75 }
76 }
77
bitfield_tuple_struct_impl(ast: &DeriveInput, fields: &FieldsUnnamed) -> Result<TokenStream>78 fn bitfield_tuple_struct_impl(ast: &DeriveInput, fields: &FieldsUnnamed) -> Result<TokenStream> {
79 let mut ast = ast.clone();
80 let width = match parse_remove_bits_attr(&mut ast)? {
81 Some(w) => w,
82 None => {
83 return Err(Error::new(
84 Span::call_site(),
85 "tuple struct field must have bits attribute",
86 ));
87 }
88 };
89
90 let ident = &ast.ident;
91
92 if width > 64 {
93 return Err(Error::new(
94 Span::call_site(),
95 "max width of bitfield field is 64",
96 ));
97 }
98
99 let bits = width as u8;
100
101 if fields.unnamed.len() != 1 {
102 return Err(Error::new(
103 Span::call_site(),
104 "tuple struct field must have exactly 1 field",
105 ));
106 }
107
108 let field_type = match &fields.unnamed.first().unwrap().ty {
109 Type::Path(t) => t,
110 _ => {
111 return Err(Error::new(
112 Span::call_site(),
113 "tuple struct field must have primitive field",
114 ));
115 }
116 };
117 let span = field_type.path.segments.first().unwrap().ident.span();
118
119 let from_u64 = quote_spanned! {
120 span => val as #field_type
121 };
122
123 let into_u64 = quote_spanned! {
124 span => val.0 as u64
125 };
126
127 let expanded = quote! {
128 #ast
129
130 impl bit_field::BitFieldSpecifier for #ident {
131 const FIELD_WIDTH: u8 = #bits;
132 type SetterType = Self;
133 type GetterType = Self;
134
135 #[inline]
136 #[allow(clippy::unnecessary_cast)]
137 fn from_u64(val: u64) -> Self::GetterType {
138 Self(#from_u64)
139 }
140
141 #[inline]
142 #[allow(clippy::unnecessary_cast)]
143 fn into_u64(val: Self::SetterType) -> u64 {
144 #into_u64
145 }
146 }
147 };
148
149 Ok(expanded)
150 }
151
bitfield_enum_impl(ast: &DeriveInput, data: &DataEnum) -> Result<TokenStream>152 fn bitfield_enum_impl(ast: &DeriveInput, data: &DataEnum) -> Result<TokenStream> {
153 let mut ast = ast.clone();
154 let width = parse_remove_bits_attr(&mut ast)?;
155 match width {
156 None => bitfield_enum_without_width_impl(&ast, data),
157 Some(width) => bitfield_enum_with_width_impl(&ast, data, width),
158 }
159 }
160
bitfield_enum_with_width_impl( ast: &DeriveInput, data: &DataEnum, width: u64, ) -> Result<TokenStream>161 fn bitfield_enum_with_width_impl(
162 ast: &DeriveInput,
163 data: &DataEnum,
164 width: u64,
165 ) -> Result<TokenStream> {
166 if width > 64 {
167 return Err(Error::new(
168 Span::call_site(),
169 "max width of bitfield enum is 64",
170 ));
171 }
172 let bits = width as u8;
173 let declare_discriminants = get_declare_discriminants_for_enum(bits, ast, data);
174
175 let ident = &ast.ident;
176 let type_name = ident.to_string();
177 let variants = &data.variants;
178 let match_discriminants = variants.iter().map(|variant| {
179 let variant = &variant.ident;
180 quote! {
181 discriminant::#variant => Ok(#ident::#variant),
182 }
183 });
184
185 let expanded = quote! {
186 #ast
187
188 impl bit_field::BitFieldSpecifier for #ident {
189 const FIELD_WIDTH: u8 = #bits;
190 type SetterType = Self;
191 type GetterType = std::result::Result<Self, bit_field::Error>;
192
193 #[inline]
194 fn from_u64(val: u64) -> Self::GetterType {
195 struct discriminant;
196 impl discriminant {
197 #(#declare_discriminants)*
198 }
199 match val {
200 #(#match_discriminants)*
201 v => Err(bit_field::Error::new(#type_name, v)),
202 }
203 }
204
205 #[inline]
206 fn into_u64(val: Self::SetterType) -> u64 {
207 val as u64
208 }
209 }
210 };
211
212 Ok(expanded)
213 }
214 // Expand to an impl of BitFieldSpecifier for an enum like:
215 //
216 // #[bitfield]
217 // #[derive(Debug, PartialEq)]
218 // enum TwoBits {
219 // Zero = 0b00,
220 // One = 0b01,
221 // Two = 0b10,
222 // Three = 0b11,
223 // }
224 //
225 // Such enums may be used as a field of a bitfield struct.
226 //
227 // #[bitfield]
228 // struct Struct {
229 // prefix: BitField1,
230 // two_bits: TwoBits,
231 // suffix: BitField5,
232 // }
233 //
bitfield_enum_without_width_impl(ast: &DeriveInput, data: &DataEnum) -> Result<TokenStream>234 fn bitfield_enum_without_width_impl(ast: &DeriveInput, data: &DataEnum) -> Result<TokenStream> {
235 let ident = &ast.ident;
236 let variants = &data.variants;
237 let len = variants.len();
238 if len.count_ones() != 1 {
239 return Err(Error::new(
240 Span::call_site(),
241 "#[bitfield] expected a number of variants which is a power of 2 when bits is not \
242 specified for the enum",
243 ));
244 }
245
246 let bits = len.trailing_zeros() as u8;
247 let declare_discriminants = get_declare_discriminants_for_enum(bits, ast, data);
248
249 let match_discriminants = variants.iter().map(|variant| {
250 let variant = &variant.ident;
251 quote! {
252 discriminant::#variant => #ident::#variant,
253 }
254 });
255
256 let expanded = quote! {
257 #ast
258
259 impl bit_field::BitFieldSpecifier for #ident {
260 const FIELD_WIDTH: u8 = #bits;
261 type SetterType = Self;
262 type GetterType = Self;
263
264 #[inline]
265 fn from_u64(val: u64) -> Self::GetterType {
266 struct discriminant;
267 impl discriminant {
268 #(#declare_discriminants)*
269 }
270 match val {
271 #(#match_discriminants)*
272 _ => unreachable!(),
273 }
274 }
275
276 #[inline]
277 fn into_u64(val: Self::SetterType) -> u64 {
278 val as u64
279 }
280 }
281 };
282
283 Ok(expanded)
284 }
285
get_declare_discriminants_for_enum( bits: u8, ast: &DeriveInput, data: &DataEnum, ) -> Vec<TokenStream>286 fn get_declare_discriminants_for_enum(
287 bits: u8,
288 ast: &DeriveInput,
289 data: &DataEnum,
290 ) -> Vec<TokenStream> {
291 let variants = &data.variants;
292 let upper_bound = 2u64.pow(bits as u32);
293 let ident = &ast.ident;
294
295 variants
296 .iter()
297 .map(|variant| {
298 let variant = &variant.ident;
299 let span = variant.span();
300
301 let assertion = quote_spanned! {span=>
302 // If IS_IN_BOUNDS is true, this evaluates to 0.
303 //
304 // If IS_IN_BOUNDS is false, this evaluates to `0 - 1` which
305 // triggers a compile error on underflow when referenced below. The
306 // error is not beautiful but does carry the span of the problematic
307 // enum variant so at least it points to the right line.
308 //
309 // error: any use of this value will cause an error
310 // --> bit_field/test.rs:10:5
311 // |
312 // 10 | OutOfBounds = 0b111111,
313 // | ^^^^^^^^^^^ attempt to subtract with overflow
314 // |
315 //
316 // error[E0080]: erroneous constant used
317 // --> bit_field/test.rs:5:1
318 // |
319 // 5 | #[bitfield]
320 // | ^^^^^^^^^^^ referenced constant has errors
321 //
322 const ASSERT: u64 = 0 - !IS_IN_BOUNDS as u64;
323 };
324
325 quote! {
326 #[allow(non_upper_case_globals)]
327 const #variant: u64 = {
328 const IS_IN_BOUNDS: bool = (#ident::#variant as u64) < #upper_bound;
329
330 #assertion
331
332 #ident::#variant as u64 + ASSERT
333 };
334 }
335 })
336 .collect()
337 }
338
bitfield_struct_impl(ast: &DeriveInput, fields: &FieldsNamed) -> Result<TokenStream>339 fn bitfield_struct_impl(ast: &DeriveInput, fields: &FieldsNamed) -> Result<TokenStream> {
340 let name = &ast.ident;
341 let vis = &ast.vis;
342 let attrs = &ast.attrs;
343 let fields = get_struct_fields(fields)?;
344 let struct_def = get_struct_def(vis, name, &fields);
345 let bits_impl = get_bits_impl(name);
346 let fields_impl = get_fields_impl(&fields);
347 let debug_fmt_impl = get_debug_fmt_impl(name, &fields);
348
349 let expanded = quote! {
350 #(#attrs)*
351 #struct_def
352 #bits_impl
353 impl #name {
354 #(#fields_impl)*
355 }
356 #debug_fmt_impl
357 };
358
359 Ok(expanded)
360 }
361
362 struct FieldSpec<'a> {
363 ident: &'a Ident,
364 ty: &'a Type,
365 expected_bits: Option<LitInt>,
366 }
367
368 // Unwrap ast to get the named fields. We only care about field names and types:
369 // "myfield : BitField3" -> ("myfield", Token(BitField3))
get_struct_fields(fields: &FieldsNamed) -> Result<Vec<FieldSpec>>370 fn get_struct_fields(fields: &FieldsNamed) -> Result<Vec<FieldSpec>> {
371 let mut vec = Vec::new();
372
373 for field in &fields.named {
374 let ident = field
375 .ident
376 .as_ref()
377 .expect("Fields::Named has named fields");
378 let ty = &field.ty;
379 let expected_bits = parse_bits_attr(&field.attrs)?;
380 vec.push(FieldSpec {
381 ident,
382 ty,
383 expected_bits,
384 });
385 }
386
387 Ok(vec)
388 }
389
390 // For example: #[bits = 1]
parse_bits_attr(attrs: &[Attribute]) -> Result<Option<LitInt>>391 fn parse_bits_attr(attrs: &[Attribute]) -> Result<Option<LitInt>> {
392 let mut expected_bits = None;
393
394 for attr in attrs {
395 if attr.path().is_ident("doc") {
396 continue;
397 }
398 if let Some(v) = try_parse_bits_attr(attr) {
399 expected_bits = Some(v);
400 continue;
401 }
402
403 return Err(Error::new_spanned(attr, "unrecognized attribute"));
404 }
405
406 Ok(expected_bits)
407 }
408
409 // This function will return None if the attribute is not #[bits = *].
try_parse_bits_attr(attr: &Attribute) -> Option<LitInt>410 fn try_parse_bits_attr(attr: &Attribute) -> Option<LitInt> {
411 if attr.path().is_ident("bits") {
412 if let Meta::NameValue(MetaNameValue {
413 value:
414 syn::Expr::Lit(syn::ExprLit {
415 lit: Lit::Int(int), ..
416 }),
417 ..
418 }) = &attr.meta
419 {
420 return Some(int).cloned();
421 }
422 }
423 None
424 }
425
parse_remove_bits_attr(ast: &mut DeriveInput) -> Result<Option<u64>>426 fn parse_remove_bits_attr(ast: &mut DeriveInput) -> Result<Option<u64>> {
427 let mut width = None;
428 let mut bits_idx = 0;
429
430 for (i, attr) in ast.attrs.iter().enumerate() {
431 if let Some(w) = try_parse_bits_attr(attr) {
432 bits_idx = i;
433 width = Some(w.base10_parse()?);
434 }
435 }
436
437 if width.is_some() {
438 ast.attrs.remove(bits_idx);
439 }
440
441 Ok(width)
442 }
443
get_struct_def(vis: &Visibility, name: &Ident, fields: &[FieldSpec]) -> TokenStream444 fn get_struct_def(vis: &Visibility, name: &Ident, fields: &[FieldSpec]) -> TokenStream {
445 let mut field_types = Vec::new();
446 for spec in fields {
447 field_types.push(spec.ty);
448 }
449
450 // `(BitField1::FIELD_WIDTH + BitField3::FIELD_WIDTH + ...)`
451 let data_size_in_bits = quote! {
452 (
453 #(
454 <#field_types as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
455 )+*
456 )
457 };
458
459 quote! {
460 #[repr(C)]
461 #vis struct #name {
462 data: [u8; #data_size_in_bits / 8],
463 }
464
465 impl #name {
466 pub fn new() -> #name {
467 let _: ::bit_field::Check<[u8; #data_size_in_bits % 8]>;
468
469 #name {
470 data: [0; #data_size_in_bits / 8],
471 }
472 }
473 }
474 }
475 }
476
477 // Implement setter and getter for all fields.
get_fields_impl(fields: &[FieldSpec]) -> Vec<TokenStream>478 fn get_fields_impl(fields: &[FieldSpec]) -> Vec<TokenStream> {
479 let mut impls = Vec::new();
480 // This vec keeps track of types before this field, used to generate the offset.
481 let current_types = &mut vec![quote!(::bit_field::BitField0)];
482
483 for spec in fields {
484 let ty = spec.ty;
485 let getter_ident = Ident::new(format!("get_{}", spec.ident).as_str(), Span::call_site());
486 let setter_ident = Ident::new(format!("set_{}", spec.ident).as_str(), Span::call_site());
487
488 // Optional #[bits = N] attribute to provide compile-time checked
489 // documentation of how many bits some field covers.
490 let check_expected_bits = spec.expected_bits.as_ref().map(|expected_bits| {
491 // If expected_bits does not match the actual number of bits in the
492 // bit field specifier, this will fail to compile with an error
493 // pointing into the #[bits = N] attribute.
494 let span = expected_bits.span();
495 quote_spanned! {span=>
496 #[allow(dead_code)]
497 const EXPECTED_BITS: [(); #expected_bits] =
498 [(); <#ty as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize];
499 }
500 });
501
502 impls.push(quote! {
503 pub fn #getter_ident(&self) -> <#ty as ::bit_field::BitFieldSpecifier>::GetterType {
504 #check_expected_bits
505 let offset = #(<#current_types as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize)+*;
506 let val = self.get(offset, <#ty as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH);
507 <#ty as ::bit_field::BitFieldSpecifier>::from_u64(val)
508 }
509
510 pub fn #setter_ident(&mut self, val: <#ty as ::bit_field::BitFieldSpecifier>::SetterType) {
511 let val = <#ty as ::bit_field::BitFieldSpecifier>::into_u64(val);
512 debug_assert!(val <= ::bit_field::max::<#ty>());
513 let offset = #(<#current_types as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize)+*;
514 self.set(offset, <#ty as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH, val)
515 }
516 });
517
518 current_types.push(quote!(#ty));
519 }
520
521 impls
522 }
523
524 // Implement setter and getter for all fields.
get_debug_fmt_impl(name: &Ident, fields: &[FieldSpec]) -> TokenStream525 fn get_debug_fmt_impl(name: &Ident, fields: &[FieldSpec]) -> TokenStream {
526 // print fields:
527 let mut impls = Vec::new();
528 for spec in fields {
529 let field_name = spec.ident.to_string();
530 let getter_ident = Ident::new(&format!("get_{}", spec.ident), Span::call_site());
531 impls.push(quote! {
532 .field(#field_name, &self.#getter_ident())
533 });
534 }
535
536 let name_str = format!("{}", name);
537 quote! {
538 impl std::fmt::Debug for #name {
539 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
540 f.debug_struct(#name_str)
541 #(#impls)*
542 .finish()
543 }
544 }
545 }
546 }
547
get_bits_impl(name: &Ident) -> TokenStream548 fn get_bits_impl(name: &Ident) -> TokenStream {
549 quote! {
550 impl #name {
551 #[inline]
552 fn check_access(&self, offset: usize, width: u8) {
553 debug_assert!(width <= 64);
554 debug_assert!(offset / 8 < self.data.len());
555 debug_assert!((offset + (width as usize)) <= (self.data.len() * 8));
556 }
557
558 #[inline]
559 pub fn get_bit(&self, offset: usize) -> bool {
560 self.check_access(offset, 1);
561
562 let byte_index = offset / 8;
563 let bit_offset = offset % 8;
564
565 let byte = self.data[byte_index];
566 let mask = 1 << bit_offset;
567
568 byte & mask == mask
569 }
570
571 #[inline]
572 pub fn set_bit(&mut self, offset: usize, val: bool) {
573 self.check_access(offset, 1);
574
575 let byte_index = offset / 8;
576 let bit_offset = offset % 8;
577
578 let byte = &mut self.data[byte_index];
579 let mask = 1 << bit_offset;
580
581 if val {
582 *byte |= mask;
583 } else {
584 *byte &= !mask;
585 }
586 }
587
588 #[inline]
589 pub fn get(&self, offset: usize, width: u8) -> u64 {
590 self.check_access(offset, width);
591 let mut val = 0;
592
593 for i in 0..(width as usize) {
594 if self.get_bit(i + offset) {
595 val |= 1 << i;
596 }
597 }
598
599 val
600 }
601
602 #[inline]
603 pub fn set(&mut self, offset: usize, width: u8, val: u64) {
604 self.check_access(offset, width);
605
606 for i in 0..(width as usize) {
607 let mask = 1 << i;
608 let val_bit_is_set = val & mask == mask;
609 self.set_bit(i + offset, val_bit_is_set);
610 }
611 }
612 }
613 }
614 }
615
616 // Only intended to be used from the bit_field crate. This macro emits the
617 // marker types bit_field::BitField0 through bit_field::BitField64.
618 #[proc_macro]
619 #[doc(hidden)]
define_bit_field_specifiers(_input: proc_macro::TokenStream) -> proc_macro::TokenStream620 pub fn define_bit_field_specifiers(_input: proc_macro::TokenStream) -> proc_macro::TokenStream {
621 let mut code = TokenStream::new();
622
623 for width in 0u8..=64 {
624 let span = Span::call_site();
625 let long_name = Ident::new(&format!("BitField{}", width), span);
626 let short_name = Ident::new(&format!("B{}", width), span);
627
628 let default_field_type = if width <= 8 {
629 quote!(u8)
630 } else if width <= 16 {
631 quote!(u16)
632 } else if width <= 32 {
633 quote!(u32)
634 } else {
635 quote!(u64)
636 };
637
638 code.extend(quote! {
639 pub struct #long_name;
640 pub use self::#long_name as #short_name;
641
642 impl BitFieldSpecifier for #long_name {
643 const FIELD_WIDTH: u8 = #width;
644 type SetterType = #default_field_type;
645 type GetterType = #default_field_type;
646
647 #[inline]
648 fn from_u64(val: u64) -> Self::GetterType {
649 val as Self::GetterType
650 }
651
652 #[inline]
653 fn into_u64(val: Self::SetterType) -> u64 {
654 val as u64
655 }
656 }
657 });
658 }
659
660 code.into()
661 }
662
663 #[cfg(test)]
664 mod tests {
665 use syn::parse_quote;
666
667 use super::*;
668
669 #[test]
end_to_end()670 fn end_to_end() {
671 let input: DeriveInput = parse_quote! {
672 #[derive(Clone)]
673 struct MyBitField {
674 a: BitField1,
675 b: BitField2,
676 c: BitField5,
677 }
678 };
679
680 let expected = quote! {
681 #[derive(Clone)]
682 #[repr(C)]
683 struct MyBitField {
684 data: [u8; (<BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
685 + <BitField2 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
686 + <BitField5 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize)
687 / 8],
688 }
689 impl MyBitField {
690 pub fn new() -> MyBitField {
691 let _: ::bit_field::Check<[
692 u8;
693 (<BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
694 + <BitField2 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
695 + <BitField5 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize)
696 % 8
697 ]>;
698
699 MyBitField {
700 data: [0; (<BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
701 + <BitField2 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
702 + <BitField5 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize)
703 / 8],
704 }
705 }
706 }
707 impl MyBitField {
708 #[inline]
709 fn check_access(&self, offset: usize, width: u8) {
710 debug_assert!(width <= 64);
711 debug_assert!(offset / 8 < self.data.len());
712 debug_assert!((offset + (width as usize)) <= (self.data.len() * 8));
713 }
714 #[inline]
715 pub fn get_bit(&self, offset: usize) -> bool {
716 self.check_access(offset, 1);
717 let byte_index = offset / 8;
718 let bit_offset = offset % 8;
719 let byte = self.data[byte_index];
720 let mask = 1 << bit_offset;
721 byte & mask == mask
722 }
723 #[inline]
724 pub fn set_bit(&mut self, offset: usize, val: bool) {
725 self.check_access(offset, 1);
726 let byte_index = offset / 8;
727 let bit_offset = offset % 8;
728 let byte = &mut self.data[byte_index];
729 let mask = 1 << bit_offset;
730 if val {
731 *byte |= mask;
732 } else {
733 *byte &= !mask;
734 }
735 }
736 #[inline]
737 pub fn get(&self, offset: usize, width: u8) -> u64 {
738 self.check_access(offset, width);
739 let mut val = 0;
740 for i in 0..(width as usize) {
741 if self.get_bit(i + offset) {
742 val |= 1 << i;
743 }
744 }
745 val
746 }
747 #[inline]
748 pub fn set(&mut self, offset: usize, width: u8, val: u64) {
749 self.check_access(offset, width);
750 for i in 0..(width as usize) {
751 let mask = 1 << i;
752 let val_bit_is_set = val & mask == mask;
753 self.set_bit(i + offset, val_bit_is_set);
754 }
755 }
756 }
757 impl MyBitField {
758 pub fn get_a(&self) -> <BitField1 as ::bit_field::BitFieldSpecifier>::GetterType {
759 let offset = <::bit_field::BitField0 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize;
760 let val = self.get(offset, <BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH);
761 <BitField1 as ::bit_field::BitFieldSpecifier>::from_u64(val)
762 }
763 pub fn set_a(&mut self, val: <BitField1 as ::bit_field::BitFieldSpecifier>::SetterType) {
764 let val = <BitField1 as ::bit_field::BitFieldSpecifier>::into_u64(val);
765 debug_assert!(val <= ::bit_field::max::<BitField1>());
766 let offset = <::bit_field::BitField0 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize;
767 self.set(offset, <BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH, val)
768 }
769 pub fn get_b(&self) -> <BitField2 as ::bit_field::BitFieldSpecifier>::GetterType {
770 let offset = <::bit_field::BitField0 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
771 + <BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize;
772 let val = self.get(offset, <BitField2 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH);
773 <BitField2 as ::bit_field::BitFieldSpecifier>::from_u64(val)
774 }
775 pub fn set_b(&mut self, val: <BitField2 as ::bit_field::BitFieldSpecifier>::SetterType) {
776 let val = <BitField2 as ::bit_field::BitFieldSpecifier>::into_u64(val);
777 debug_assert!(val <= ::bit_field::max::<BitField2>());
778 let offset = <::bit_field::BitField0 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
779 + <BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize;
780 self.set(offset, <BitField2 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH, val)
781 }
782 pub fn get_c(&self) -> <BitField5 as ::bit_field::BitFieldSpecifier>::GetterType {
783 let offset = <::bit_field::BitField0 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
784 + <BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
785 + <BitField2 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize;
786 let val = self.get(offset, <BitField5 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH);
787 <BitField5 as ::bit_field::BitFieldSpecifier>::from_u64(val)
788 }
789 pub fn set_c(&mut self, val: <BitField5 as ::bit_field::BitFieldSpecifier>::SetterType) {
790 let val = <BitField5 as ::bit_field::BitFieldSpecifier>::into_u64(val);
791 debug_assert!(val <= ::bit_field::max::<BitField5>());
792 let offset = <::bit_field::BitField0 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
793 + <BitField1 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize
794 + <BitField2 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH as usize;
795 self.set(offset, <BitField5 as ::bit_field::BitFieldSpecifier>::FIELD_WIDTH, val)
796 }
797 }
798 impl std::fmt::Debug for MyBitField {
799 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
800 f.debug_struct("MyBitField")
801 .field("a", &self.get_a())
802 .field("b", &self.get_b())
803 .field("c", &self.get_c())
804 .finish()
805 }
806 }
807 };
808
809 assert_eq!(
810 bitfield_impl(&input).unwrap().to_string(),
811 expected.to_string()
812 );
813 }
814 }
815